2016-04-16 07:27:27 +08:00
|
|
|
#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;
|
|
|
|
|
2016-07-18 11:00:09 +08:00
|
|
|
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)
|
|
|
|
{}
|
|
|
|
|
2016-04-16 07:27:27 +08:00
|
|
|
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() {
|
2016-07-18 11:00:09 +08:00
|
|
|
globalCheckpoint() = Checkpoint();
|
2016-04-16 07:27:27 +08:00
|
|
|
}
|
|
|
|
|
2016-04-29 06:28:23 +08:00
|
|
|
#if defined(__GNUC__)
|
|
|
|
#define CHECKPOINT_FUNCTION_NAME __PRETTY_FUNCTION__
|
|
|
|
#else
|
|
|
|
#define CHECKPOINT_FUNCTION_NAME __func__
|
|
|
|
#endif
|
|
|
|
|
2016-07-18 11:00:09 +08:00
|
|
|
#define CHECKPOINT(msg) globalCheckpoint() = Checkpoint(__FILE__, CHECKPOINT_FUNCTION_NAME, __LINE__, msg);
|
2016-04-16 07:27:27 +08:00
|
|
|
|
|
|
|
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
|