#ifndef LOGGING_H
#define LOGGING_H
#include <stdio.h>
#include <pthread.h>
#include "mega-dylib-utils.h"
void verboseLog(const char* format, ...) __printflike(1, 2);
void log(const char* __restrict format, ...) __printflike(1, 2);
void alwaysLog(const char* __restrict format, ...) __printflike(1, 2);
void warning(const char* format, ...) __printflike(1, 2);
void terminate(const char* format, ...) __printflike(1, 2) __attribute__((noreturn));
void dumpLogAndExit(bool logFinishTime=true);
void setVerbose(bool level);
void setReturnNonZeroOnTerminate();
void setWarnAnErrorPrefixes(const char* warn, const char* err);
struct LoggingContext {
LoggingContext(const std::string& N);
LoggingContext(const std::string& N, WarningTargets T);
void taint();
bool isTainted();
const std::string& name();
const WarningTargets& targets();
private:
const std::string _name;
const WarningTargets _warnings;
bool _tainted;
};
void setLoggingContext(std::shared_ptr<LoggingContext>& context);
std::shared_ptr<LoggingContext> getLoggingContext();
void runBody(void* Ctx);
pthread_key_t getLoggingContextKey(void);
template <typename BodyFtor>
std::function<void(void)>* heapSafe(BodyFtor&& Body, std::shared_ptr<LoggingContext> context)
{
auto retval = new std::function<void(void)>([ B = std::move(Body), context ]() mutable {
if (!context || !context->isTainted()) {
void* oldCtx = pthread_getspecific(getLoggingContextKey());
setLoggingContext(context);
try {
B();
} catch (std::string exception) {
WarningTargets warningTargets = context->targets();
for (auto& target : warningTargets.second) {
warningTargets.first->configurations[target.first].architectures[target.second].results.failure = exception;
}
if (context) {
context->taint();
}
} catch (...) {
if (context) {
context->taint();
}
}
pthread_setspecific(getLoggingContextKey(), oldCtx);
}
});
return retval;
}
template <typename BodyFtor>
void cacheBuilderDispatchAsync(dispatch_queue_t queue, BodyFtor&& Body)
{
dispatch_async_f(queue, heapSafe(Body, getLoggingContext()), runBody);
}
template <typename BodyFtor>
void cacheBuilderDispatchGroupAsync(dispatch_group_t group, dispatch_queue_t queue, BodyFtor&& Body)
{
dispatch_group_async_f(group, queue, heapSafe(Body, getLoggingContext()), runBody);
}
template <typename BodyFtor>
void cacheBuilderDispatchSync(dispatch_queue_t queue, BodyFtor&& Body)
{
dispatch_sync_f(queue, heapSafe(Body, getLoggingContext()), runBody);
}
#endif