#ifndef SUPPORT_ASSERT_CHECKPOINT_H #define SUPPORT_ASSERT_CHECKPOINT_H #include <csignal> #include <iostream> #include <cstdlib> struct Checkpoint { const char* file; const char* func; int line; const char* msg; Checkpoint() : file(nullptr), func(nullptr), line(-1), msg(nullptr) {} Checkpoint(const char* xfile, const char* xfunc, int xline, const char* xmsg) : file(xfile), func(xfunc), line(xline), msg(xmsg) {} template <class Stream> void print(Stream& s) const { if (!file) { s << "NO CHECKPOINT\n"; return; } s << file << ":" << line << " " << func << ": Checkpoint"; if (msg) s << " '" << msg << "'"; s << std::endl; } }; inline Checkpoint& globalCheckpoint() { static Checkpoint C; return C; } inline void clearCheckpoint() { globalCheckpoint() = Checkpoint(); } #if defined(__GNUC__) #define CHECKPOINT_FUNCTION_NAME __PRETTY_FUNCTION__ #else #define CHECKPOINT_FUNCTION_NAME __func__ #endif #define CHECKPOINT(msg) globalCheckpoint() = Checkpoint(__FILE__, CHECKPOINT_FUNCTION_NAME, __LINE__, msg); inline void checkpointSignalHandler(int signal) { if (signal == SIGABRT) { globalCheckpoint().print(std::cerr); } else { std::cerr << "Unexpected signal " << signal << " received\n"; } std::_Exit(EXIT_FAILURE); } inline bool initCheckpointHandler() { typedef void(*HandlerT)(int); static bool isInit = false; if (isInit) return true; HandlerT prev_h = std::signal(SIGABRT, checkpointSignalHandler); if (prev_h == SIG_ERR) { std::cerr << "Setup failed.\n"; std::_Exit(EXIT_FAILURE); } isInit = true; return false; } static bool initDummy = initCheckpointHandler(); #endif