-#define LOG_PREFIX { \
- auto _thread_ = this_thread::get_id(); \
- int _tid_ = thread_name_map[_thread_]; \
- if (_tid_==0) \
- _tid_ = thread_name_map[_thread_] = ++next_thread_num; \
- auto _utime_ = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count() % 1000000000; \
- cerr << setfill('0') << dec << left << setw(9) << _utime_ << " "; \
- cerr << setfill(' ') << log_thread_prefix << left << setw(2) << _tid_; \
- cerr << " " << setw(20) << __FILE__ << " " << setw(18) << __func__; \
-}
-#define LOG_THIS_POINTER { \
- int _self_ = instance_name_map[this]; \
- if (_self_==0) \
- _self_ = instance_name_map[this] = ++next_instance_num; \
- cerr << "#" << left << setw(2) << _self_ << " "; \
-}
-
-#define LOG_NONMEMBER(_x_) { \
- lock _cel_(cerr_mutex); \
- LOG_PREFIX; \
- cerr << _x_ << endl; \
-}
-#define LOG(_x_) { \
- lock _cel_(cerr_mutex); \
- LOG_PREFIX; \
- LOG_THIS_POINTER; \
- cerr << _x_ << endl; \
-}
+struct locked_ostream {
+ ostream & s;
+ lock l;
+ ~locked_ostream() { s << endl; }
+ template <typename U>
+ locked_ostream & operator<<(U && u) { s << u; return *this; }
+
+ typedef std::ostream& (*ostream_manipulator)(ostream&);
+ locked_ostream & operator<<(ostream_manipulator manip) { s << manip; return *this; }
+};
+
+locked_ostream && _log_prefix(locked_ostream && f, const string & file, const string & func);
+locked_ostream && _log_member(locked_ostream && f, const void *ptr);
+#define _log_nonmember(f, ptr) f
+
+#define _LOG(_context_) _context_(_log_prefix(locked_ostream{cerr, lock(cerr_mutex)}, __FILE__, __func__), (const void *)this)
+
+#define LOG_NONMEMBER _LOG(_log_nonmember)
+#define LOG _LOG(_log_member)