summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/logger/logger_kernel_1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/logger/logger_kernel_1.cpp')
-rw-r--r--ml/dlib/dlib/logger/logger_kernel_1.cpp498
1 files changed, 498 insertions, 0 deletions
diff --git a/ml/dlib/dlib/logger/logger_kernel_1.cpp b/ml/dlib/dlib/logger/logger_kernel_1.cpp
new file mode 100644
index 000000000..093cd29a8
--- /dev/null
+++ b/ml/dlib/dlib/logger/logger_kernel_1.cpp
@@ -0,0 +1,498 @@
+// Copyright (C) 2006 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#ifndef DLIB_LOGGER_KERNEL_1_CPp_
+#define DLIB_LOGGER_KERNEL_1_CPp_
+
+#include "logger_kernel_1.h"
+#include <iostream>
+#include <sstream>
+
+namespace dlib
+{
+
+// ----------------------------------------------------------------------------------------
+
+ void set_all_logging_output_streams (
+ std::ostream& out_
+ )
+ {
+ logger::global_data& gd = logger::get_global_data();
+ auto_mutex M(gd.m);
+ gd.loggers.reset();
+ while (gd.loggers.move_next())
+ {
+ gd.loggers.element()->out.rdbuf(out_.rdbuf());
+ gd.loggers.element()->hook.clear();
+ }
+
+ gd.set_output_stream("",out_);
+
+ // set the default hook to be an empty member function pointer
+ logger::hook_mfp hook;
+ gd.set_output_hook("",hook);
+ }
+
+ void set_all_logging_levels (
+ const log_level& new_level
+ )
+ {
+ logger::global_data& gd = logger::get_global_data();
+ auto_mutex M(gd.m);
+ gd.loggers.reset();
+ while (gd.loggers.move_next())
+ {
+ gd.loggers.element()->cur_level = new_level;
+ }
+
+ gd.set_level("",new_level);
+ }
+
+ void set_all_logging_headers (
+ const print_header_type& new_header
+ )
+ {
+ logger::global_data& gd = logger::get_global_data();
+ auto_mutex M(gd.m);
+ gd.loggers.reset();
+ while (gd.loggers.move_next())
+ {
+ gd.loggers.element()->print_header = new_header;
+ }
+
+ gd.set_logger_header("",new_header);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ namespace logger_helper_stuff
+ {
+ class helper
+ {
+ public:
+ helper()
+ {
+ std::ostringstream sout;
+ print_default_logger_header(sout,"some_name",LDEBUG,0);
+ }
+ };
+ // do this to make sure all the static members of print_default_logger_header get
+ // initialized when the program turns on.
+ static helper a;
+ // make a logger to make extra sure the static global_data object gets
+ // initialized before any threads start up. Also do this so that there is always
+ // at least one logger so that the global data won't be deleted until the
+ // program is terminating.
+ static logger log("dlib");
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void print_default_logger_header (
+ std::ostream& out,
+ const std::string& logger_name,
+ const log_level& l,
+ const uint64 thread_id
+ )
+ {
+ using namespace std;
+ static timestamper ts;
+ static const uint64 first_time = ts.get_timestamp();
+
+ const uint64 cur_time = (ts.get_timestamp() - first_time)/1000;
+ streamsize old_width = out.width(); out.width(5);
+ out << cur_time << " " << l.name;
+ out.width(old_width);
+
+ out << " [" << thread_id << "] " << logger_name << ": ";
+ }
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// global_data stuff
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ logger::global_data::
+ ~global_data (
+ )
+ {
+ unregister_thread_end_handler(*this,&global_data::thread_end_handler);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ logger::global_data::
+ global_data(
+ ) :
+ next_thread_name(1)
+ {
+ // make sure the main program thread always has id 0. Since there is
+ // a global logger object declared in this file we should expect that
+ // the global_data object will be initialized in the main program thread
+ // so if we call get_thread_id() now we should get the main thread id.
+ thread_id_type main_id = get_thread_id();
+ uint64 id_zero = 0;
+ thread_names.add(main_id,id_zero);
+
+ // set up the defaults
+ auto_flush_table.val = true;
+ streambuf_table.val = std::cout.rdbuf();
+ header_table.val = print_default_logger_header;
+
+ // also allocate an initial buffer for hook based logging
+ hookbuf.buffer.reserve(1000);
+ }
+
+ logger::global_data::level_container::
+ level_container (
+ ) : val(300,"ERROR") {}
+
+// ----------------------------------------------------------------------------------------
+
+ template <typename T>
+ const T& search_tables (
+ const T& c,
+ const std::string& name
+ )
+ {
+ if (c.table.size() == 0 || name.size() == 0)
+ return c;
+
+ const std::string::size_type pos = name.find_first_of(".");
+ const std::string first = name.substr(0,pos);
+ std::string last;
+ if (pos != std::string::npos)
+ last = name.substr(pos+1);
+
+ if (c.table.is_in_domain(first))
+ {
+ return search_tables(*c.table[first], last);
+ }
+ else
+ {
+ return c;
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <typename T, typename U>
+ void assign_tables (
+ T& c,
+ const std::string& name,
+ const U& val
+ )
+ {
+ if (name.size() == 0)
+ {
+ c.val = val;
+ c.table.clear();
+ return;
+ }
+
+ const std::string::size_type pos = name.find_first_of(".");
+ std::string first = name.substr(0,pos);
+ std::string last;
+ if (pos != std::string::npos)
+ last = name.substr(pos+1);
+
+ if (c.table.is_in_domain(first))
+ {
+ assign_tables(*c.table[first], last, val);
+ }
+ else
+ {
+ std::unique_ptr<T> temp (new T);
+ temp->val = c.val;
+ assign_tables(*temp, last, val);
+ c.table.add(first,temp);
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ const log_level logger::global_data::
+ level (
+ const std::string& name
+ ) const
+ {
+ auto_mutex M(m);
+ return search_tables(level_table, name).val;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void logger::global_data::
+ set_level (
+ const std::string& name,
+ const log_level& new_level
+ )
+ {
+ auto_mutex M(m);
+ assign_tables(level_table, name, new_level);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ bool logger::global_data::
+ auto_flush (
+ const std::string& name
+ ) const
+ {
+ auto_mutex M(m);
+ return search_tables(auto_flush_table, name).val;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void logger::global_data::
+ set_auto_flush (
+ const std::string& name,
+ bool enabled
+ )
+ {
+ auto_mutex M(m);
+ assign_tables(auto_flush_table, name, enabled);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ std::streambuf* logger::global_data::
+ output_streambuf (
+ const std::string& name
+ )
+ {
+ auto_mutex M(m);
+ return search_tables(streambuf_table, name).val;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void logger::global_data::
+ set_output_stream (
+ const std::string& name,
+ std::ostream& out_
+ )
+ {
+ auto_mutex M(m);
+ assign_tables( streambuf_table, name, out_.rdbuf());
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void logger::global_data::
+ set_output_stream (
+ const std::string& name,
+ std::streambuf& buf
+ )
+ {
+ auto_mutex M(m);
+ assign_tables( streambuf_table, name, &buf);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ logger::hook_mfp logger::global_data::
+ output_hook (
+ const std::string& name
+ )
+ {
+ auto_mutex M(m);
+ return search_tables(hook_table, name).val;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void logger::global_data::
+ set_output_hook (
+ const std::string& name,
+ const hook_mfp& hook
+ )
+ {
+ auto_mutex M(m);
+ assign_tables( hook_table, name, hook);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ print_header_type logger::global_data::
+ logger_header (
+ const std::string& name
+ )
+ {
+ auto_mutex M(m);
+ return search_tables(header_table, name).val;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void logger::global_data::
+ set_logger_header (
+ const std::string& name,
+ print_header_type ph
+ )
+ {
+ auto_mutex M(m);
+ assign_tables(header_table, name, ph);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ logger::global_data& logger::get_global_data()
+ {
+ // Allocate the global_data on the heap rather than on the stack because
+ // we want to guard against the case where this static object would be destroyed
+ // during program termination BEFORE all logger objects are destroyed.
+ static global_data* gd = new global_data;
+ return *gd;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void logger::global_data::
+ thread_end_handler (
+ )
+ {
+ auto_mutex M(m);
+ thread_id_type id = get_thread_id();
+ thread_id_type junkd;
+ uint64 junkr;
+ thread_names.remove(id,junkd,junkr);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ uint64 logger::global_data::
+ get_thread_name (
+ )
+ {
+ thread_id_type id = get_thread_id();
+ uint64 thread_name;
+ if (thread_names.is_in_domain(id))
+ {
+ thread_name = thread_names[id];
+ }
+ else
+ {
+ if (is_dlib_thread(id))
+ register_thread_end_handler(*this,&global_data::thread_end_handler);
+ thread_name = next_thread_name;
+ thread_names.add(id,thread_name);
+ thread_name = next_thread_name;
+ ++next_thread_name;
+ }
+ return thread_name;
+ }
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// logger_stream stuff
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ void logger::logger_stream::
+ print_header_and_stuff (
+ )
+ {
+ if (!been_used)
+ {
+ log.gd.m.lock();
+
+ // Check if the output hook is setup. If it isn't then we print the logger
+ // header like normal. Otherwise we need to remember to clear out the output
+ // stringstream we always write to.
+ if (log.hook.is_set() == false)
+ {
+ log.logger_header()(log.out,log.name(),l,log.gd.get_thread_name());
+ }
+ else
+ {
+ // Make sure the hook buffer doesn't have any old data in it before we start
+ // logging a new message into it.
+ log.gd.hookbuf.buffer.resize(0);
+ }
+ been_used = true;
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ void logger::logger_stream::
+ print_end_of_line (
+ )
+ {
+ auto_unlock M(log.gd.m);
+
+ if (log.hook.is_set() == false)
+ {
+ if (log.auto_flush_enabled)
+ log.out << std::endl;
+ else
+ log.out << "\n";
+ }
+ else
+ {
+ // Make sure the buffer is a proper C-string
+ log.gd.hookbuf.buffer.push_back('\0');
+ // call the output hook with all the info regarding this log message.
+ log.hook(log.name(), l, log.gd.get_thread_name(), &log.gd.hookbuf.buffer[0]);
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// logger stuff
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ logger::
+ logger (
+ const std::string& name_
+ ) :
+ gd(get_global_data()),
+ logger_name(name_),
+ out(gd.output_streambuf(logger_name)),
+ cur_level(gd.level(logger_name))
+ {
+ DLIB_ASSERT(name_[0] != '\0',
+ "\tlogger::logger()"
+ << "\n\tYou can't make a logger with an empty name"
+ << "\n\tthis: " << this
+ );
+
+ auto_mutex M(gd.m);
+ logger* temp = this;
+ gd.loggers.add(temp);
+
+ // load the appropriate settings
+ print_header = gd.logger_header(logger_name);
+ auto_flush_enabled = gd.auto_flush(logger_name);
+ hook = gd.output_hook(logger_name);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ logger::
+ ~logger (
+ )
+ {
+ gd.m.lock();
+ gd.loggers.destroy(this);
+ // if this was the last logger then delete the global data
+ if (gd.loggers.size() == 0)
+ {
+ gd.m.unlock();
+ delete &gd;
+ }
+ else
+ {
+ gd.m.unlock();
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+}
+
+#endif // DLIB_LOGGER_KERNEL_1_CPp_
+