PageRenderTime 108ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/dlib/logger/logger_kernel_1.h

https://github.com/exi/gravisim
C Header | 476 lines | 286 code | 76 blank | 114 comment | 13 complexity | f945135888c6f4e0886cd30452ecf7b8 MD5 | raw file
  1. // Copyright (C) 2006 Davis E. King (davisking@users.sourceforge.net)
  2. // License: Boost Software License See LICENSE.txt for the full license.
  3. #ifndef DLIB_LOGGER_KERNEl_1_
  4. #define DLIB_LOGGER_KERNEl_1_
  5. #include "../threads.h"
  6. #include "../misc_api.h"
  7. #include "../set.h"
  8. #include "logger_kernel_abstract.h"
  9. #include <limits>
  10. #include <cstring>
  11. #include "../algs.h"
  12. #include "../assert.h"
  13. #include "../uintn.h"
  14. #include "../map.h"
  15. #include "../smart_pointers.h"
  16. namespace dlib
  17. {
  18. // ----------------------------------------------------------------------------------------
  19. class log_level
  20. {
  21. public:
  22. log_level(
  23. int priority_,
  24. const char* name_
  25. ) :
  26. priority(priority_)
  27. {
  28. strncpy(name,name_,19);
  29. name[19] = '\0';
  30. }
  31. int priority;
  32. char name[20];
  33. };
  34. const log_level LALL (std::numeric_limits<int>::min(),"ALL");
  35. const log_level LNONE (std::numeric_limits<int>::max(),"NONE");
  36. const log_level LTRACE(-100,"TRACE");
  37. const log_level LDEBUG(0 ,"DEBUG");
  38. const log_level LINFO (100,"INFO ");
  39. const log_level LWARN (200,"WARN ");
  40. const log_level LERROR(300,"ERROR");
  41. const log_level LFATAL(400,"FATAL");
  42. // ----------------------------------------------------------------------------------------
  43. void set_all_logging_output_streams (
  44. std::ostream& out
  45. );
  46. void set_all_logging_levels (
  47. const log_level& new_level
  48. );
  49. // ----------------------------------------------------------------------------------------
  50. void print_default_logger_header (
  51. std::ostream& out,
  52. const std::string& logger_name,
  53. const log_level& l,
  54. const uint64 thread_id
  55. );
  56. // ----------------------------------------------------------------------------------------
  57. class logger
  58. {
  59. /*!
  60. INITIAL VALUE
  61. - print_header == print_default_logger_header
  62. - out.rdbuf() == std::cout.rdbuf()
  63. - cur_level == LERROR
  64. - auto_flush_enabled == true
  65. CONVENTION
  66. - print_header == logger_header()
  67. - out.rdbuf() == output_streambuf()
  68. - cur_level == level()
  69. - logger_name == name()
  70. - auto_flush_enabled == auto_flush()
  71. - logger::gd::loggers == a set containing all currently existing loggers.
  72. - logger::gd::m == the mutex used to lock everything in the logger
  73. - logger::gd::thread_names == a map of thread ids to thread names.
  74. - logger::gd::next_thread_name == the next thread name that will be given out
  75. to a thread when we find that it isn't already in thread_names.
  76. !*/
  77. class logger_stream
  78. {
  79. /*!
  80. INITIAL VALUE
  81. - been_used == false
  82. CONVENTION
  83. - enabled == is_enabled()
  84. - if (been_used) then
  85. - logger::gd::m is locked
  86. - someone has used the << operator to write something to the
  87. output stream.
  88. !*/
  89. public:
  90. logger_stream (
  91. const log_level& l_,
  92. logger& log_
  93. ) :
  94. l(l_),
  95. log(log_),
  96. been_used(false),
  97. enabled (l.priority >= log.cur_level.priority)
  98. {}
  99. inline ~logger_stream(
  100. )
  101. {
  102. if (!been_used)
  103. {
  104. return;
  105. }
  106. else
  107. {
  108. print_end_of_line();
  109. }
  110. }
  111. bool is_enabled (
  112. ) const { return enabled; }
  113. template <typename T>
  114. inline logger_stream& operator << (
  115. const T& item
  116. )
  117. {
  118. if (!enabled)
  119. {
  120. return *this;
  121. }
  122. else
  123. {
  124. print_header_and_stuff();
  125. log.out << item;
  126. return *this;
  127. }
  128. }
  129. private:
  130. void print_header_and_stuff (
  131. );
  132. /*!
  133. ensures
  134. - if (!been_used) then
  135. - prints the logger header
  136. - locks log.gd.m
  137. - #been_used == true
  138. !*/
  139. void print_end_of_line (
  140. );
  141. /*!
  142. ensures
  143. - prints a newline to log.out
  144. - unlocks log.gd.m
  145. !*/
  146. const log_level& l;
  147. logger& log;
  148. bool been_used;
  149. const bool enabled;
  150. };
  151. friend class logger_stream;
  152. public:
  153. logger (
  154. const char* name_
  155. );
  156. virtual ~logger (
  157. );
  158. const std::string& name (
  159. ) const { return logger_name; }
  160. logger_stream operator << (
  161. const log_level& l
  162. ) const { return logger_stream(l,const_cast<logger&>(*this)); }
  163. bool is_child_of (
  164. const logger& log
  165. ) const
  166. {
  167. return (name().find(log.name() + ".") == 0) || (log.name() == name());
  168. }
  169. const log_level level (
  170. ) const
  171. {
  172. auto_mutex M(gd.m);
  173. return log_level(cur_level);
  174. };
  175. void set_level (
  176. const log_level& new_level
  177. )
  178. {
  179. auto_mutex M(gd.m);
  180. gd.loggers.reset();
  181. while (gd.loggers.move_next())
  182. {
  183. if (gd.loggers.element()->is_child_of(*this))
  184. gd.loggers.element()->cur_level = new_level;
  185. }
  186. gd.set_level(logger_name, new_level);
  187. }
  188. bool auto_flush (
  189. ) const
  190. {
  191. auto_mutex M(gd.m);
  192. return auto_flush_enabled;
  193. };
  194. void set_auto_flush (
  195. bool enabled
  196. )
  197. {
  198. auto_mutex M(gd.m);
  199. gd.loggers.reset();
  200. while (gd.loggers.move_next())
  201. {
  202. if (gd.loggers.element()->is_child_of(*this))
  203. gd.loggers.element()->auto_flush_enabled = enabled;
  204. }
  205. gd.set_auto_flush(logger_name, enabled);
  206. }
  207. std::streambuf* output_streambuf (
  208. )
  209. {
  210. auto_mutex M(gd.m);
  211. return out.rdbuf();
  212. }
  213. void set_output_stream (
  214. std::ostream& out_
  215. )
  216. {
  217. auto_mutex M(gd.m);
  218. gd.loggers.reset();
  219. while (gd.loggers.move_next())
  220. {
  221. if (gd.loggers.element()->is_child_of(*this))
  222. gd.loggers.element()->out.rdbuf(out_.rdbuf());
  223. }
  224. gd.set_output_stream(logger_name, out_);
  225. }
  226. typedef void (*print_header_type)(
  227. std::ostream& out,
  228. const std::string& logger_name,
  229. const log_level& l,
  230. const uint64 thread_id
  231. );
  232. print_header_type logger_header (
  233. ) const { return print_header; }
  234. void set_logger_header (
  235. print_header_type ph
  236. )
  237. {
  238. auto_mutex M(gd.m);
  239. gd.loggers.reset();
  240. while (gd.loggers.move_next())
  241. {
  242. if (gd.loggers.element()->is_child_of(*this))
  243. gd.loggers.element()->print_header = ph;
  244. }
  245. gd.set_logger_header(logger_name, ph);
  246. }
  247. private:
  248. struct global_data
  249. {
  250. rmutex m;
  251. set<logger*>::kernel_1b loggers;
  252. map<thread_id_type,uint64>::kernel_1b thread_names;
  253. uint64 next_thread_name;
  254. global_data (
  255. );
  256. ~global_data(
  257. );
  258. uint64 get_thread_name (
  259. );
  260. /*!
  261. requires
  262. - m is locked
  263. ensures
  264. - returns a unique id for the calling thread. also makes the number
  265. small and nice unlike what you get from get_thread_id()
  266. !*/
  267. void thread_end_handler (
  268. );
  269. /*!
  270. ensures
  271. - removes the terminated thread from thread_names
  272. !*/
  273. struct level_container
  274. {
  275. level_container ();
  276. log_level val;
  277. map<std::string,scoped_ptr<level_container> >::kernel_1b_c table;
  278. } level_table;
  279. const log_level level (
  280. const std::string& name
  281. ) const;
  282. /*!
  283. ensures
  284. - returns the level loggers with the given name are supposed
  285. to have
  286. !*/
  287. void set_level (
  288. const std::string& name,
  289. const log_level& new_level
  290. );
  291. /*!
  292. ensures
  293. - for all children C of name:
  294. - #level(C) == new_level
  295. - if name == "" then
  296. - for all loggers L:
  297. - #level(L) == new_level
  298. !*/
  299. struct auto_flush_container
  300. {
  301. bool val;
  302. map<std::string,scoped_ptr<auto_flush_container> >::kernel_1b_c table;
  303. } auto_flush_table;
  304. bool auto_flush (
  305. const std::string& name
  306. ) const;
  307. /*!
  308. ensures
  309. - returns the auto_flush value loggers with the given name are supposed
  310. to have
  311. !*/
  312. void set_auto_flush (
  313. const std::string& name,
  314. bool enabled
  315. );
  316. /*!
  317. ensures
  318. - for all children C of name:
  319. - #auto_flush_enabled(C) == enabled
  320. - if name == "" then
  321. - for all loggers L:
  322. - #auto_flush_enabled(L) == enabled
  323. !*/
  324. struct output_streambuf_container
  325. {
  326. std::streambuf* val;
  327. map<std::string,scoped_ptr<output_streambuf_container> >::kernel_1b_c table;
  328. } streambuf_table;
  329. std::streambuf* output_streambuf (
  330. const std::string& name
  331. );
  332. /*!
  333. ensures
  334. - returns the streambuf loggers with the given name are supposed
  335. to have
  336. !*/
  337. void set_output_stream (
  338. const std::string& name,
  339. std::ostream& out_
  340. );
  341. /*!
  342. ensures
  343. - for all children C of name:
  344. - #output_streambuf(C) == out_.rdbuf()
  345. - if name == "" then
  346. - for all loggers L:
  347. - #output_streambuf(L) == out_.rdbuf()
  348. !*/
  349. struct logger_header_container
  350. {
  351. print_header_type val;
  352. map<std::string,scoped_ptr<logger_header_container> >::kernel_1b_c table;
  353. } header_table;
  354. print_header_type logger_header (
  355. const std::string& name
  356. );
  357. /*!
  358. ensures
  359. - returns the header function loggers with the given name are supposed
  360. to have
  361. !*/
  362. void set_logger_header (
  363. const std::string& name,
  364. print_header_type ph
  365. );
  366. /*!
  367. ensures
  368. - for all children C of name:
  369. - #logger_header(C) == ph
  370. - if name == "" then
  371. - for all loggers L:
  372. - #logger_header(L) == ph
  373. !*/
  374. }; // end of struct global_data
  375. static global_data& get_global_data();
  376. friend void set_all_logging_levels (
  377. const log_level& new_level
  378. );
  379. friend void set_all_logging_output_streams (
  380. std::ostream& out
  381. );
  382. global_data& gd;
  383. const std::string logger_name;
  384. print_header_type print_header;
  385. bool auto_flush_enabled;
  386. std::ostream out;
  387. log_level cur_level;
  388. // restricted functions
  389. logger(const logger&); // copy constructor
  390. logger& operator=(const logger&); // assignment operator
  391. };
  392. // ----------------------------------------------------------------------------------------
  393. }
  394. #ifdef NO_MAKEFILE
  395. #include "logger_kernel_1.cpp"
  396. #endif
  397. #endif // DLIB_LOGGER_KERNEl_1_