1 #ifndef SUPPORT_ASSERT_CHECKPOINT_H
2 #define SUPPORT_ASSERT_CHECKPOINT_H
3
4 #include <csignal>
5 #include <iostream>
6 #include <cstdlib>
7
8 struct Checkpoint {
9 const char* file;
10 const char* func;
11 int line;
12 const char* msg;
13
CheckpointCheckpoint14 Checkpoint() : file(nullptr), func(nullptr), line(-1), msg(nullptr) {}
CheckpointCheckpoint15 Checkpoint(const char* xfile, const char* xfunc, int xline, const char* xmsg)
16 : file(xfile), func(xfunc), line(xline), msg(xmsg)
17 {}
18
19 template <class Stream>
printCheckpoint20 void print(Stream& s) const {
21 if (!file) {
22 s << "NO CHECKPOINT\n";
23 return;
24 }
25 s << file << ":" << line << " " << func << ": Checkpoint";
26 if (msg)
27 s << " '" << msg << "'";
28 s << std::endl;
29 }
30 };
31
globalCheckpoint()32 inline Checkpoint& globalCheckpoint() {
33 static Checkpoint C;
34 return C;
35 }
36
clearCheckpoint()37 inline void clearCheckpoint() {
38 globalCheckpoint() = Checkpoint();
39 }
40
41 #if defined(__GNUC__)
42 #define CHECKPOINT_FUNCTION_NAME __PRETTY_FUNCTION__
43 #else
44 #define CHECKPOINT_FUNCTION_NAME __func__
45 #endif
46
47 #define CHECKPOINT(msg) globalCheckpoint() = Checkpoint(__FILE__, CHECKPOINT_FUNCTION_NAME, __LINE__, msg);
48
checkpointSignalHandler(int signal)49 inline void checkpointSignalHandler(int signal) {
50 if (signal == SIGABRT) {
51 globalCheckpoint().print(std::cerr);
52 } else {
53 std::cerr << "Unexpected signal " << signal << " received\n";
54 }
55 std::_Exit(EXIT_FAILURE);
56 }
57
initCheckpointHandler()58 inline bool initCheckpointHandler() {
59 typedef void(*HandlerT)(int);
60 static bool isInit = false;
61 if (isInit) return true;
62 HandlerT prev_h = std::signal(SIGABRT, checkpointSignalHandler);
63 if (prev_h == SIG_ERR) {
64 std::cerr << "Setup failed.\n";
65 std::_Exit(EXIT_FAILURE);
66 }
67 isInit = true;
68 return false;
69 }
70
71 static bool initDummy = initCheckpointHandler();
72
73 #endif
74