#ifndef threaded_log_h
#define threaded_log_h
-#include <iomanip>
-#include <iostream>
-#include <stdio.h>
-#include <map>
-#include "lock.h"
-
-extern mutex cerr_mutex;
-extern std::map<std::thread::id, int> thread_name_map;
-extern int next_thread_num;
-extern std::map<void *, int> instance_name_map;
-extern int next_instance_num;
-extern char log_thread_prefix;
-
-template <class A>
-struct iterator_pair : public std::pair<A, A> {
- explicit iterator_pair(const A & first, const A & second) : std::pair<A, A>(first, second) {}
+#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; }
};
-template <class A>
-const struct iterator_pair<A> make_iterator_pair(const A & first, const A & second) {
- return iterator_pair<A>(first, second);
-}
-
-template <class A, class B>
-std::ostream & operator<<(std::ostream &o, const std::pair<A,B> &d) {
- o << "<" << d.first << "," << d.second << ">";
- return o;
-}
-
-template <class A>
-std::ostream & operator<<(std::ostream &o, const iterator_pair<A> &d) {
- o << "[";
- for (auto i=d.first; i!=d.second; i++) {
- o << *i;
- auto j(i);
- if (++j != d.second)
- o << ", ";
- }
- o << "]";
- return o;
-}
+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_PREFIX { \
- cerr_mutex.lock(); \
- 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_ = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count() % 1000000000; \
- std::cerr << std::setfill('0') << std::dec << std::left << std::setw(9) << _utime_ << " "; \
- std::cerr << std::setfill(' ') << log_thread_prefix << std::left << std::setw(2) << _tid_; \
- std::cerr << " " << std::setw(20) << __FILE__ << " " << std::setw(18) << __func__; \
-}
-#define LOG_THIS_POINTER { \
- int _self_ = instance_name_map[this]; \
- if (_self_==0) \
- _self_ = instance_name_map[this] = ++next_instance_num; \
- std::cerr << "#" << std::setw(2) << _self_; \
-}
-#define LOG_SUFFIX { \
- cerr_mutex.unlock(); \
-}
+#define LOG_NONMEMBER _log_prefix(locked_ostream{std::cerr, _log_lock()}, __FILE__, __func__)
+#define LOG _log_member(LOG_NONMEMBER, (const void *)this)
-#define LOG_NONMEMBER(_x_) { \
- LOG_PREFIX; \
- std::cerr << _x_ << std::endl; \
- LOG_SUFFIX; \
-}
-#define LOG(_x_) { \
- LOG_PREFIX; \
- LOG_THIS_POINTER; \
- std::cerr << _x_ << std::endl; \
- LOG_SUFFIX; \
-}
-#define LOG_FUNC_ENTER { \
- LOG_PREFIX; \
- LOG_THIS_POINTER; \
- std::cerr << "lid=" << lid; \
- std::cerr << std::endl; \
- LOG_SUFFIX; \
-}
-#define LOG_FUNC_ENTER_SERVER { \
- LOG_PREFIX; \
- LOG_THIS_POINTER; \
- std::cerr << "lid=" << lid; \
- std::cerr << " client=" << id << "," << xid; \
- std::cerr << std::endl; \
- LOG_SUFFIX; \
-}
-#define LOG_FUNC_EXIT { \
- LOG_PREFIX; \
- LOG_THIS_POINTER; \
- std::cerr << "return" << lid; \
- std::cerr << std::endl; \
- LOG_SUFFIX; \
-}
+#define IF_LEVEL(level) if(_log_debug_level() >= abs(level))
#endif