All random numbers generated via one PRNG seeded in one place.
[invirt/third/libt4.git] / threaded_log.h
index 706e2b7..9a83bfb 100644 (file)
@@ -1,61 +1,26 @@
 #ifndef threaded_log_h
 #define threaded_log_h
 
-#include "types.h"
-
-extern mutex cerr_mutex;
-extern map<thread::id, int> thread_name_map;
-extern int next_thread_num;
-extern map<void *, int> instance_name_map;
-extern int next_instance_num;
-extern char log_thread_prefix;
-
-namespace std {
-    // This is an awful hack.  But sticking this in std:: makes it possible for
-    // ostream_iterator to use it.
-    template <class A, class B>
-    ostream & operator<<(ostream &o, const pair<A,B> &d) {
-        return o << "<" << d.first << "," << d.second << ">";
-    }
-}
-
-template <class A>
-typename enable_if<is_iterable<A>::value && !is_same<A,string>::value, ostream>::type &
-operator<<(ostream &o, const A &a) {
-    return o << "[" << implode(a, ", ") << "]";
-}
-
-#define LOG_PREFIX { \
-    auto _thread_ = std::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 << "#" << 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; \
-}
-
-extern int DEBUG_LEVEL;
-
-#define IF_LEVEL(level) if(DEBUG_LEVEL >= abs(level))
+#include <string>
+#include <ostream>
+
+struct locked_ostream {
+    std::ostream & s;
+    lock l;
+    locked_ostream(locked_ostream &&) = default;
+    ~locked_ostream() { s << std::endl; }
+    template <typename U>
+    locked_ostream & operator<<(U && u) { s << u; 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);
+int _log_debug_level();
+lock _log_lock();
+
+#define LOG_NONMEMBER _log_prefix(locked_ostream{std::cerr, _log_lock()}, __FILE__, __func__)
+#define LOG           _log_member(LOG_NONMEMBER, (const void *)this)
+
+#define IF_LEVEL(level) if(_log_debug_level() >= abs(level))
 
 #endif