6 extern mutex cerr_mutex;
7 extern map<thread::id, int> thread_name_map;
8 extern int next_thread_num;
9 extern map<void *, int> instance_name_map;
10 extern int next_instance_num;
11 extern char log_thread_prefix;
14 // This is an awful hack. But sticking this in std:: makes it possible for
15 // ostream_iterator to use it.
16 template <class A, class B>
17 ostream & operator<<(ostream &o, const pair<A,B> &d) {
18 return o << "<" << d.first << "," << d.second << ">";
23 typename enable_if<is_iterable<A>::value && !is_same<A,string>::value, ostream>::type &
24 operator<<(ostream &o, const A &a) {
25 return o << "[" << implode(a, ", ") << "]";
28 #define LOG_PREFIX { \
29 auto _thread_ = std::this_thread::get_id(); \
30 int _tid_ = thread_name_map[_thread_]; \
32 _tid_ = thread_name_map[_thread_] = ++next_thread_num; \
33 auto _utime_ = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count() % 1000000000; \
34 cerr << setfill('0') << dec << left << setw(9) << _utime_ << " "; \
35 cerr << setfill(' ') << log_thread_prefix << left << setw(2) << _tid_; \
36 cerr << " " << setw(20) << __FILE__ << " " << setw(18) << __func__; \
38 #define LOG_THIS_POINTER { \
39 int _self_ = instance_name_map[this]; \
41 _self_ = instance_name_map[this] = ++next_instance_num; \
42 cerr << "#" << setw(2) << _self_; \
45 #define LOG_NONMEMBER(_x_) { \
46 lock _cel_(cerr_mutex); \
48 cerr << _x_ << endl; \
51 lock _cel_(cerr_mutex); \
54 cerr << _x_ << endl; \
57 extern int DEBUG_LEVEL;
59 #define IF_LEVEL(level) if(DEBUG_LEVEL >= abs(level))