#ifndef threaded_log_h
#define threaded_log_h
-#include <iomanip>
-#include <iostream>
-#include <stdio.h>
-#include <map>
-#include "lock.h"
+#include "types.h"
extern mutex cerr_mutex;
-extern std::map<std::thread::id, int> thread_name_map;
+extern map<thread::id, int> thread_name_map;
extern int next_thread_num;
-extern std::map<void *, int> instance_name_map;
+extern 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) {}
-};
-
-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;
+namespace std {
+ // 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>
-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;
+typename enable_if<is_const_iterable<A>::value && !is_same<A,string>::value, ostream>::type &
+operator<<(ostream &o, const A &a) {
+ return o << "[" << implode(a, ", ") << "]";
}
#define LOG_PREFIX { \
- cerr_mutex.lock(); \
- auto _thread_ = std::this_thread::get_id(); \
+ 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_ = 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__; \
+ 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; \
- std::cerr << "#" << std::setw(2) << _self_; \
-}
-#define LOG_SUFFIX { \
- cerr_mutex.unlock(); \
+ cerr << "#" << left << setw(2) << _self_ << " "; \
}
#define LOG_NONMEMBER(_x_) { \
+ lock _cel_(cerr_mutex); \
LOG_PREFIX; \
- std::cerr << _x_ << std::endl; \
- LOG_SUFFIX; \
+ cerr << _x_ << endl; \
}
#define LOG(_x_) { \
+ lock _cel_(cerr_mutex); \
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; \
+ cerr << _x_ << endl; \
}
+extern int DEBUG_LEVEL;
+
+#define IF_LEVEL(level) if(DEBUG_LEVEL >= abs(level))
+
#endif