|
Boost-Commit : |
From: john.groups_at_[hidden]
Date: 2008-01-29 20:39:14
Author: jtorjo
Date: 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
New Revision: 43017
URL: http://svn.boost.org/trac/boost/changeset/43017
Log:
[logging]
v0.21.7, 30 jan 2008
- updated docs : about caching/destruction
- not using after_being_destroyed.hpp anymore - no need (see @ref after_destruction).
Removed:
sandbox/logging/lib/logging/tests/test_after_destroyed/
Text files modified:
sandbox/logging/boost/logging/detail/after_being_destroyed.hpp | 3
sandbox/logging/boost/logging/detail/cache_before_init.hpp | 32 +++-----
sandbox/logging/boost/logging/detail/format_write_detail.hpp | 4
sandbox/logging/boost/logging/detail/logger.hpp | 22 -----
sandbox/logging/boost/logging/detail/logger_base.hpp | 18 ----
sandbox/logging/boost/logging/detail/macros.hpp | 86 +++++++----------------
sandbox/logging/boost/logging/detail/manipulator.hpp | 108 ++++++++++++++++++++++++++---
sandbox/logging/boost/logging/detail/raw_doc/acknowledgments.hpp | 2
sandbox/logging/boost/logging/detail/raw_doc/after_destruction.hpp | 111 ++++++++----------------------
sandbox/logging/boost/logging/detail/raw_doc/caching.hpp | 98 +++++++++++++++------------
sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp | 4
sandbox/logging/boost/logging/detail/raw_doc/defining_your_logger_filter.hpp | 8 ++
sandbox/logging/boost/logging/detail/raw_doc/headers_to_include.hpp | 12 ++-
sandbox/logging/boost/logging/detail/raw_doc/table_of_contents.hpp | 2
sandbox/logging/boost/logging/detail/raw_doc/todo.hpp | 16 ++++
sandbox/logging/boost/logging/detail/tags.hpp | 4
sandbox/logging/boost/logging/format/destination/defaults.hpp | 1
sandbox/logging/boost/logging/gather/ostream_like.hpp | 7 -
sandbox/logging/boost/logging/writer/on_dedicated_thread.hpp | 85 +++++++++++++++++++++--
sandbox/logging/lib/logging/internal/vc8/loggingvc8/test_now.cpp | 141 ++++++++++++++++++++-------------------
sandbox/logging/lib/logging/samples/scenarios/cache_before_init.cpp | 1
sandbox/logging/lib/logging/samples/starter/my_app_log.cpp | 3
sandbox/logging/lib/logging/samples/starter/my_app_log.h | 10 +-
23 files changed, 424 insertions(+), 354 deletions(-)
Modified: sandbox/logging/boost/logging/detail/after_being_destroyed.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/after_being_destroyed.hpp (original)
+++ sandbox/logging/boost/logging/detail/after_being_destroyed.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -17,6 +17,9 @@
#ifndef JT28092007_after_being_destroyed_HPP_DEFINED
#define JT28092007_after_being_destroyed_HPP_DEFINED
+// see "Using the logger(s)/filter(s) after they've been destroyed" section in the documentation
+#error this is obsolete
+
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
Modified: sandbox/logging/boost/logging/detail/cache_before_init.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/cache_before_init.hpp (original)
+++ sandbox/logging/boost/logging/detail/cache_before_init.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -51,9 +51,6 @@
#endif
}
-#ifndef BOOST_LOG_BEFORE_INIT_LOCK_RESOURCE_CLASS
-#define BOOST_LOG_BEFORE_INIT_LOCK_RESOURCE_CLASS ::boost::logging::lock_resource_finder::single_thread
-#endif
#if defined( BOOST_LOG_BEFORE_INIT_USE_CACHE_FILTER) || defined( BOOST_LOG_BEFORE_INIT_USE_LOG_ALL)
//////////////////////////////////////////////////////////////////
@@ -69,9 +66,8 @@
*/
-template<class msg_type, class lock_resource = BOOST_LOG_BEFORE_INIT_LOCK_RESOURCE_CLASS > struct cache_before_init {
+template<class msg_type> struct cache_before_init {
private:
- typedef typename lock_resource::template finder<bool>::type is_cache_enabled_data;
typedef bool (*is_enabled_func)();
struct message {
@@ -98,18 +94,18 @@
bool is_using_cache;
};
+
public:
+ cache_before_init() : m_is_caching_off(false) {}
+
bool is_cache_turned_off() const {
- {
- typename is_cache_enabled_data::read info(m_is_caching_off);
- bool is_caching_off = info.use();
- if ( is_caching_off)
- return true; // cache has been turned on
- }
+ if ( m_is_caching_off)
+ return true; // cache has been turned off
// now we go the slow way - use mutex to see if cache is turned off
mutex::scoped_lock lk(m_cs);
- return !(m_cache.is_using_cache);
+ m_is_caching_off = !(m_cache.is_using_cache);
+ return m_is_caching_off;
}
template<class writer_type> void turn_cache_off(const writer_type & writer_) {
@@ -121,11 +117,6 @@
m_cache.is_using_cache = false;
}
- {
- typename is_cache_enabled_data::write info(m_is_caching_off);
- info.use() = true;
- }
-
// dump messages
typename cache::message_array msgs;
{
@@ -174,7 +165,7 @@
mutable cache m_cache;
/**
IMPORTANT: to make sure we know when the cache is off as efficiently as possible, I have this mechanism:
- - first, query m_is_enabled, which at the beginning is false (this is very efficient, we can use TSS here)
+ - first, query m_is_enabled, which at the beginning is false
- if this is true, it's clear that caching has been turned off
- if this is false, we don't know for sure, thus, continue to ask
@@ -183,14 +174,14 @@
- if m_cache.is_using_cache is false, caching has been turned off
- set m_is_enabled to true, thus this will propagate to all threads soon (depending on your lock_resource)
*/
- is_cache_enabled_data m_is_caching_off;
+ mutable bool m_is_caching_off;
};
#else
//////////////////////////////////////////////////////////////////
// Messages that were logged before initializing the log - NOT Caching them
-template<class msg_type, class lock_resource = BOOST_LOG_BEFORE_INIT_LOCK_RESOURCE_CLASS > struct cache_before_init {
+template<class msg_type> struct cache_before_init {
template<class writer_type> void on_do_write(msg_type & msg, const writer_type & writer) const {
writer(msg);
}
@@ -198,6 +189,7 @@
template<class writer_type> void turn_cache_off(const writer_type & writer) {
}
+ bool is_cache_turned_off() const { return true; }
};
#endif
Modified: sandbox/logging/boost/logging/detail/format_write_detail.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/format_write_detail.hpp (original)
+++ sandbox/logging/boost/logging/detail/format_write_detail.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -83,7 +83,7 @@
@endcode
In the above case, @c formatter::idx() is called, then @c formatter::time(), then @c formatter::append_newline(). Now, the destinations are called:
-_at_c destinatino::cout(), and then @c destination::file().
+@c destination::cout(), and then @c destination::file().
Most of the time this is ok, and this is what the @ref msg_route::simple "default router" does. However, there are other routers
in the msg_route namespace. For instance, take a look at msg_route::with_route class.
@@ -95,7 +95,7 @@
Once the formatters and destinations are added, and you know the route, you have an extra object - the format_and_write - which
contains the logic for calling the formatters and destinations.
-The format_and_write class knows how to call the formatters and destination @c objects. Usually you'll be happy with the
+The format_and_write class knows how to call the formatters and destinations @em objects. Usually you'll be happy with the
format_and_write::simple class - which simply calls @c operator() on the formatters , and @c operator() on the destinations.
Otherwise, take a look at format_and_write namespace.
Modified: sandbox/logging/boost/logging/detail/logger.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/logger.hpp (original)
+++ sandbox/logging/boost/logging/detail/logger.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -97,10 +97,7 @@
public:
// called after all data has been gathered
void on_do_write(msg_type & msg) const {
- if ( logger_base_type::is_still_alive() )
- cache().on_do_write( msg, call_do_write(*this) );
- else
- logger_base_type::call_after_destroyed(msg);
+ cache().on_do_write( msg, call_do_write(*this) );
}
virtual void do_write(msg_type&) const = 0;
@@ -141,13 +138,6 @@
m_writer = &m_original_logger->writer();
}
- // if we set_after_destroyed, set the one we forward to as well
- virtual void set_after_destroyed(typename log_base::after_destroyed_func f) {
- log_base::set_after_destroyed(f);
- if ( m_original_logger)
- m_original_logger->set_after_destroyed(f);
- }
-
virtual void do_write(msg_type &a) const {
(*m_writer)(a);
}
@@ -249,10 +239,7 @@
// called after all data has been gathered
void on_do_write(msg_type & msg) const {
- if ( logger_base_type::is_still_alive() )
- cache().on_do_write( msg, writer() );
- else
- logger_base_type::call_after_destroyed(msg);
+ cache().on_do_write( msg, writer() );
}
private:
void init() {
@@ -303,10 +290,7 @@
// called after all data has been gathered
void on_do_write(msg_type & msg) const {
- if ( logger_base_type::is_still_alive() )
- cache().on_do_write( msg, writer() );
- else
- logger_base_type::call_after_destroyed(msg);
+ cache().on_do_write( msg, writer() );
}
private:
write_msg *m_writer;
Modified: sandbox/logging/boost/logging/detail/logger_base.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/logger_base.hpp (original)
+++ sandbox/logging/boost/logging/detail/logger_base.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -22,7 +22,8 @@
#endif
#include <boost/logging/detail/fwd.hpp>
-#include <boost/logging/detail/after_being_destroyed.hpp>
+// see "Using the logger(s)/filter(s) after they've been destroyed" section in the documentation
+//#include <boost/logging/detail/after_being_destroyed.hpp>
#ifndef JT28092007_logger_HPP_DEFINED
#error donot include this directly. include <boost/logging/logging.hpp> instead
@@ -120,26 +121,13 @@
*/
template<class gather_msg , class write_msg, class dummy = override > struct logger_base
: detail::default_cache_keeper< detail::cache_before_init<typename detail::find_gather_if_default<gather_msg>::msg_type > >,
- detail::common_base_holder<gather_msg, write_msg>,
- after_being_destroyed<dummy> {
+ detail::common_base_holder<gather_msg, write_msg> {
typedef detail::cache_before_init<typename detail::find_gather_if_default<gather_msg>::msg_type > cache_type;
typedef detail::default_cache_keeper< cache_type > cache_base;
using cache_base::cache;
typedef logger<gather_msg, write_msg> subclass_type;
- typedef after_being_destroyed<dummy> after_being_destroyed_base;
typedef detail::common_base_holder<gather_msg, write_msg> common_base_type;
- typedef typename after_being_destroyed_base::after_destroyed_func after_destroyed_func ;
-
- virtual void set_after_destroyed(after_destroyed_func f) {
- if ( f == after_being_destroyed_base::m_after_being_destroyed )
- // avoid infinite calls (since this can be forwarded back and forth - to the
- // forward logger and back)
- return;
- after_being_destroyed_base::m_after_being_destroyed = f;
- // we have a forwarder - forward it to that as well
- common_base_type::common_base()->set_after_destroyed(f);
- }
protected:
logger_base() {}
Modified: sandbox/logging/boost/logging/detail/macros.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/macros.hpp (original)
+++ sandbox/logging/boost/logging/detail/macros.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -411,38 +411,35 @@
In the former case, most of the time you won't notice the extra virtual function call, and the compilation time will be faster.
-\n\n
+\n
@subsubsection macros_compile_time_fast Fast Compilation time
- this is turned on by default on debug mode
- this is turned off by default on release mode
- to force it, define BOOST_LOG_COMPILE_FAST_ON directive
+- applies only to logs that are @ref declare_define "declared/defined using BOOST_DECLARE_LOG and BOOST_DEFINE_LOG macros"
+ - this is @em transparent to you, the programmer
+- to see what headers you should include, @ref headers_to_include "click here"
-FIXME explain about what to include
-\n\n
+\n
@subsubsection macros_compile_time_slow Slow Compilation time
- this is turned off by default on debug mode
- this is turned on by default on release mode
- to force it, define BOOST_LOG_COMPILE_FAST_OFF directive
-
-FIXME explain about what to include
-
-In case you want to have both possibilities available to you (fast compilation and slow compilation), you'll want to take a look at
-the @ref starter_project "the starter project".
-
-
-
-
+- applies only to logs that are @ref declare_define "declared/defined using BOOST_DECLARE_LOG and BOOST_DEFINE_LOG macros"
+ - this is @em transparent to you, the programmer
+- to see what headers you should include, @ref headers_to_include "click here"
+\n
@subsubsection boost_log_compile_results Compile time sample (and results)
Recently I created a sample (compile_time) to test the effect of @c BOOST_LOG_COMPILE_FAST_ON.
The results were not as promising as I had hoped. However, still, when @c BOOST_LOG_COMPILE_FAST_ON is on,
-will compile faster by 20-40%. Noting that this is just an simple example, the results might not be that conclusive.
+will compile faster by 30-40%. Noting that this is just an simple example, the results might not be that conclusive.
Anyway, here they are:
@@ -543,55 +540,26 @@
#ifdef BOOST_LOG_COMPILE_FAST
// ****** Fast compile ******
-#define BOOST_DECLARE_LOG(name,type) ::boost::logging::logger_holder< type > & name ();
-
-#ifdef BOOST_LOG_AFTER_BEING_DESTROYED_LEAK_LOGGER
- // leak the loggers
- #define BOOST_DEFINE_LOG(name,type) ::boost::logging::logger_holder< type > & name () \
- { static ::boost::logging::logger_holder_by_value< type > *l = new ::boost::logging::logger_holder< type > ; return *l; } \
- namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( name () ); }
-
- #define BOOST_DEFINE_LOG_WITH_ARGS(name,type, args) ::boost::logging::logger_holder< type > & name () \
- { static ::boost::logging::logger_holder_by_value< type > *l = new ::boost::logging::logger_holder< type > ( args ); return *l; } \
- namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( name () ); }
+#define BOOST_DECLARE_LOG(name,type) ::boost::logging::logger_holder< type > & name (); \
+ namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( name () ); }
-#else
+#define BOOST_DEFINE_LOG(name,type) ::boost::logging::logger_holder< type > & name () \
+ { static ::boost::logging::logger_holder_by_value< type > l; return l; }
- // don't leak
- #define BOOST_DEFINE_LOG(name,type) ::boost::logging::logger_holder< type > & name () \
- { static ::boost::logging::logger_holder_by_value< type > l; return l; } \
- namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( name () ); }
-
- #define BOOST_DEFINE_LOG_WITH_ARGS(name,type, args) ::boost::logging::logger_holder< type > & name () \
- { static ::boost::logging::logger_holder_by_value< type > l ( args ); return l; } \
- namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( name () ); }
-#endif
+#define BOOST_DEFINE_LOG_WITH_ARGS(name,type, args) ::boost::logging::logger_holder< type > & name () \
+ { static ::boost::logging::logger_holder_by_value< type > l ( args ); return l; }
#else
// don't compile fast
-#define BOOST_DECLARE_LOG(name,type) type* name ();
+#define BOOST_DECLARE_LOG(name,type) type* name (); \
+ namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( * name () ); }
-#ifdef BOOST_LOG_AFTER_BEING_DESTROYED_LEAK_LOGGER
- // leak the loggers
- #define BOOST_DEFINE_LOG(name,type) type* name () \
- { static type *l = new type; return l; } \
- namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( * name () ); }
-
- #define BOOST_DEFINE_LOG_WITH_ARGS(name,type, args) type* name () \
- { static type *l = new type ( args ); return l; } \
- namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( * name () ); }
-#else
+#define BOOST_DEFINE_LOG(name,type) type* name () \
+ { static type l; return &l; }
- // don't leak
- #define BOOST_DEFINE_LOG(name,type) type* name () \
- { static type l; return &l; } \
- namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( * name () ); }
-
- #define BOOST_DEFINE_LOG_WITH_ARGS(name,type, args) type* name () \
- { static type l ( args ); return &l; } \
- namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( * name () ); }
-#endif
+#define BOOST_DEFINE_LOG_WITH_ARGS(name,type, args) type* name () \
+ { static type l ( args ); return &l; }
#endif
@@ -603,14 +571,14 @@
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Filter Macros
-#define BOOST_DECLARE_LOG_FILTER(name,type) type* name ();
-#define BOOST_DEFINE_LOG_FILTER(name,type) type * name () \
- { static type l; return &l; } \
+#define BOOST_DECLARE_LOG_FILTER(name,type) type* name (); \
namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( * name () ); }
+#define BOOST_DEFINE_LOG_FILTER(name,type) type * name () \
+ { static type l; return &l; }
+
#define BOOST_DEFINE_LOG_FILTER_WITH_ARGS(name,type, args) type * name () \
- { static type l ( args ); return &l; } \
- namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( * name () ); }
+ { static type l ( args ); return &l; }
Modified: sandbox/logging/boost/logging/detail/manipulator.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/manipulator.hpp (original)
+++ sandbox/logging/boost/logging/detail/manipulator.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -47,7 +47,7 @@
- @ref manipulator_generic
- @ref manipulator_create
- @ref manipulator_share_data
-
+- @ref manipulator_manipulate
\n\n\n
@@ -262,7 +262,7 @@
I've already provided a class you can derive from , when this is the case: the non_const_context class.
@code
-struct my_file : destination::class_<my_file,destination_base,op_equal_has_context>, non_const_context<std::ofstream> {
+struct my_file : destination::class_<my_file,destination_base,op_equal_has_context>, destination::non_const_context<std::ofstream> {
std::string m_filename;
bool operator==(const my_file & other) { return m_filename == other.m_filename; }
@@ -275,9 +275,60 @@
\n\n\n
+@section manipulator_manipulate Modifying a manipulator's state
+
+When it comes to keeping its state, a manipulator (formatter or destination) instance, has 2 possibilities:
+-# either all its member data is constant - in which case you can't manipulate it (you can't modify it), OR
+-# it has non const information, which can change, and thus, some can be manipulated
+
+In the former case, all the member functions the manipulator exposes are <tt>const</tt>ant.
+
+In the latter case,
+- your manipulator class can have member functions that can change its state (non-const member functions).
+- your manipulator class @b must use the non_const_context class to hold all its non-const state
+
+What this guarantees is @ref non_const_pointer_semantics "pointer-like semantics".
+
+Assume that you have your logger that uses formatters and destinations. You've added a manipulator to your logger,
+and at a later time, you want to modify it (the manipulator, that is). To achieve this, you'll create a copy, and modify that one (this will work
+because of the @ref non_const_pointer_semantics "pointer-like semantics"):
+
+Example 1: reusing the same %destination for 2 logs
+
+@code
+destination::file out("out.txt");
+g_l_dbg()->writer().add_destination(out);
+g_l_app()->writer().add_destination(out);
+@endcode
+
+\n
+Example 2: allow resetting/clearing a destination's stream
+
+@code
+// allow resetting a destination's stream
+destination::stream g_out(std::cout);
+g_l()->writer().add_destintination(g_out);
+
+// assuming this uses g_l(), this will output to std::cout
+L_ << "hello world";
+
+g_out.stream(&std::cerr);
+// assuming this uses g_l(), this will output to std::cerr
+L_ << "hello world 2";
+
+g_out.clear();
+// assuming this uses g_l(), this will not output anything
+L_ << "hello world 3";
+
+@endcode
+
+
+
+
+\n\n\n
@section manipulator_use_it Using loggers in code
-Now that you've @ref manipulator_generic "added" formatters and/or destinations, you'll @ref macros_use "define the macros through which you'll do logging",
+Now that you've @ref manipulator_generic "added" formatters and/or destinations, you'll @ref defining_logger_macros "define the macros through which you'll do logging",
and then do logging in your code:
@code
@@ -389,15 +440,14 @@
-/**
- In case your manipulator (formatter or destination) needs to hold non-const context information, it can to derive from this.
- This automatically creates a shared pointer to the context information.
+/** @brief In case your manipulator (formatter or destination) needs to hold non-const context information, it can to derive from this.
+This automatically creates a shared pointer to the context information.
- Also, it provides the following operations:
+Also, it provides the following operations:
- @c context(), which returns a <tt>context_type &</tt> reference
+@c context(), which returns a <tt>context_type &</tt> reference
- Example:
+Example:
@code
struct write_to_file : destination_base, destination::non_const_context<std::ofstream> {
@@ -408,9 +458,27 @@
};
@endcode
+@section non_const_pointer_semantics non_const_context - Pointer-like semantics
+
+Using non_const_context guarantees @em pointer-like semantics: if you copy-construct or copy-assign a value, both values will point to the same context:
+
+@code
+write_to_file a, b = a;
+a.file_name("t1.txt");
+// a == b (a's state == b's state)
+
+write_to_file c, d;
+c.file_name("t2.txt");
+// c != d (c's state != d's state)
+
+d = c;
+c.file_name("t3.txt");
+// c == d (c's state == d's state)
+@endcode
+
- @remarks
- In case your manipulator has constant data, you don't need this
+@remarks
+In case your manipulator has constant data, you don't need this
*/
template<class context_type> struct non_const_context {
@@ -525,7 +593,15 @@
/**
@brief Formatter is a manipulator. It allows you to format the message before writing it to the destination(s)
-_at_sa manipulator, manipulator::non_const_context
+Examples of formatters are : @ref formatter::time_t "prepend the time", @ref formatter::high_precision_time_t "prepend high-precision time",
+@ref formatter::idx_t "prepend the index of the message", etc.
+
+
+See:
+- @ref manipulator "The manipulator namespace"
+- @ref manipulator_manipulate "Modifying a formatter's state"
+- @ref manipulator::non_const_context "formatter::non_const_context"
+
*/
namespace formatter {
namespace detail {
@@ -577,9 +653,13 @@
/**
@brief Destination is a manipulator. It contains a place where the message, after being formatted, is to be written to.
-Some viable destinations are : the console, a file, a socket, etc.
+Some viable destinations are : @ref destination::cout_t "the console", @ref destination::file_t "a file", a socket, etc.
+
+See:
+- @ref manipulator "The manipulator namespace"
+- @ref manipulator_manipulate "Modifying a destination's state"
+- @ref manipulator::non_const_context "formatter::non_const_context"
-_at_sa manipulator, manipulator::non_const_context
*/
namespace destination {
Modified: sandbox/logging/boost/logging/detail/raw_doc/acknowledgments.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/acknowledgments.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/acknowledgments.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -18,7 +18,7 @@
- Lucian Ciufudean - for giving me thorough feedback on the documentation, even though he's a Java freak...
- Andrei Alexandrescu - for reminding me that the default syntax should be soooo easy... Thus, named_logger was born!
- Amit Jain - for giving me quite a lot of criticism, but who made me make the docs a lot easier (or at least I hope so :))
-
+- Daniel Kruger - for helping me with the "destruction of global objects" issue
*/
Modified: sandbox/logging/boost/logging/detail/raw_doc/after_destruction.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/after_destruction.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/after_destruction.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -5,21 +5,10 @@
- @ref after_destruction_can_happen
- @ref after_destruction_avoid
-- @ref after_destruction_logger
- - @ref after_destruction_ignore
- - @ref after_destruction_write
- - @ref after_destruction_leak
-- @ref after_destruction_filter
+- @ref after_destruction_solution
-\n\n
-FIXME this is obsolete, many thanks to Daniel Kruger ("destructing of global objects" thread)
-http://groups.google.ro/group/comp.lang.c++.moderated/tree/browse_frm/thread/17987673016b2098/d4c6bdcdca1e8fe9?hl=ro&rnum=1&_done=%2Fgroup%2Fcomp.lang.c%2B%2B.moderated%2Fbrowse_frm%2Fthread%2F17987673016b2098%3Fhl%3Dro%26#doc_aa38c20511f81615
-
-So the solution should be: if in a translation unit you have a static instance of some class, and in its destructor you might end up doing logging, you should include the logging header (which will do the initialization trick)
---> same thing needs to apply to filters
---> in BOOST_DECLARE_LOG/LOG_FILTER -> need to have the init trick.
\n\n
@@ -31,90 +20,52 @@
- thus, it will be destroyed @em after the logger
- if in its destructor it tries to use the logger, there we go - logger is used after it's been destroyed.
-\n\n
-_at_section after_destruction_avoid Avoiding the issue: making sure it never happens
-
-The easiest way to make sure you don't run into this problem, is this:
-- if you know you have a global object of class A and
-- you'll use a logger in your A's destructor (directly or indirectly),
-
-Then:
-- make sure you use it in the A's constructor as well
-- this way, @em always, the logger will be instantiated before your global object,
- thus destroyed after your global object
-
-
-\n\n
-_at_section after_destruction_logger Using the logger(s) after they've been destroyed
-
-In this case, you have 3 options:
--# ignore this
--# have a function to write to, after the logger is destroyed (default)
--# leak the logger object
\n\n
-_at_subsection after_destruction_ignore Ignoring this case
-
-To ignore this issue altogether, define BOOST_LOG_AFTER_BEING_DESTROYED_IGNORE directive globally.
-
-
-\n\n
-_at_subsection after_destruction_write Write to function (default)
-
-You can have a raw (non-member) function to write to, in case the logger is used after being destroyed. This is the default.
-Also, you can force it by defining BOOST_LOG_AFTER_BEING_DESTROYED_WRITE_TO_FUNCTION directive globally.
-
-In this case, your loggers need to be global objects. We rely on the fact that after the object is destroyed,
-the memory occupied by it won't be overwritten by the system. So basically you can have a @em bool member "is_alive"
-which we set to false in the logger's destructor.
+@section after_destruction_avoid Avoiding the issue: making sure it never happens
-By default, this raw function does nothing. You can overwrite it:
+Many thanks to Daniel Kruger for helping me with this:
+- http://groups.google.ro/group/comp.lang.c++.moderated/tree/browse_frm/thread/17987673016b2098/d4c6bdcdca1e8fe9?hl=ro&rnum=1&_done=%2Fgroup%2Fcomp.lang.c%2B%2B.moderated%2Fbrowse_frm%2Fthread%2F17987673016b2098%3Fhl%3Dro%26#doc_aa38c20511f81615
+- http://groups.google.ro/group/comp.lang.c++.moderated/tree/browse_frm/thread/17987673016b2098/d4c6bdcdca1e8fe9?hl=ro&rnum=1&_done=%2Fgroup%2Fcomp.lang.c%2B%2B.moderated%2Fbrowse_frm%2Fthread%2F17987673016b2098%3Fhl%3Dro%26#doc_f506c2b42f21dad9
+The way to handle this is: since we can't handle initialization between translation units, we can handle initialization within the same translation unit.
+In the same translation unit, if we have:
@code
-void call_after_log_destruction(const std::string& str) {
- std::cout << str;
-}
-...
-
-g_l()->set_after_destroyed( call_after_log_destruction);
+static A a;
+static B b;
@endcode
-The raw function has one argument : the string you use to write to your destination. Unless you overwrite it (@ref BOOST_LOG_DESTINATION_MSG), it's std::string.
-
-
-
-\n\n
-_at_subsection after_destruction_leak Leaking the logger(s)
-
-To avoid the problem, you can also choose to leak the logger - thus, it will never be destroyed, thus we won't run into this problem.
-To choose this, define the BOOST_LOG_AFTER_BEING_DESTROYED_LEAK_LOGGER directive globally.
-
+... we're guaranteed @c a is initialized before @c b. In other words, if in a translation unit @c a is defined before @c b,
+@c a will be initialized before @c b.
+Apply this to our problem:
+- we just need some object that will reference the logger, to be defined before the global object that might end up using the logger in its destructor
+ - note: referencing the logger will imply it gets constructed first
+- this way, the logger will be created before the global object, and thus be destroyed after it
+In every translation unit that has a global object that might end up using logger(s) on its destructor,
+we need to create some object that will reference those loggers before the global object's definition.
-\n\n
-_at_section after_destruction_filter Using the filter(s) after they've been destroyed
-
-Filters, unlike loggers, are much simpler classes. Thus, you don't need to do anything for a filter - once it's destroyed,
-its memory will not be overwritten by the system, so that if the filter was on, will still remain on or if it was off, will still be off.
+Therefore, the amazing solution:
-For this to work:
--# all filters need to be global objects
--# the <em>data members</em> of the filter classes need to be trivial
-
-For the latter case, what I mean is that they should not point to dynamically allocated data (which, when destructed, would be released).
-For example:
-- @c int is a trivial type
-- @c std::string is @em not a trivial type (points to memory, which it releases on destructor)
-- @c std::vector is @em not a trivial type
-- <tt>char [256]</tt> is a trivial type
+@code
+// exposistion only
+#define BOOST_DECLARE_LOG(name,type) type* name (); \
+ namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( * name () ); }
+@endcode
-Or, you can simply leak the data members.
+When declaring the logger, we create a dummy static - in each translation unit -, that uses the logger; this will ensure the
+logger is created before the global object that will use it.
-The filter classes that come with this library are safe to use.
+@section after_destruction_solution The solution
+All you need to do is :
+- \#include the header file that declares the logs in all translation units that have global objects that could log from their destructor.
+- of course, to be sure, you could \#include that header in all translation units :)
+@note
+This applies to filters as well.
*/
Modified: sandbox/logging/boost/logging/detail/raw_doc/caching.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/caching.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/caching.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -4,10 +4,10 @@
@page caching Caching messages before logs are initialized
- @ref caching_why
-- @ref caching_BOOST_LOG_BEFORE_INIT_CACHE_FILTER
- @ref caching_BOOST_LOG_BEFORE_INIT_LOG_ALL
+- @ref caching_BOOST_LOG_BEFORE_INIT_CACHE_FILTER
+ - @ref caching_BOOST_LOG_BEFORE_INIT_CACHE_FILTER_the_catch
- @ref caching_BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT
-- @ref caching_ts
@section caching_why Caching - why is it needed?
@@ -47,95 +47,105 @@
- Cache messages that are written before logs are initialized. When logs are initialized, all these cached messages are logged
- Ignore messages that are written before the logs are initialized
-<b>By default, for each log, cache is turned on. To turn cache off (mark the log as initialized), just call @c turn_cache_off() on it.
+<b>By default, for each log, cache is turned on. To turn cache off (mark the log as initialized), just call @c mark_as_initialized() on it.
You'll see that I'm doing this on all examples that come with the library.</b>
-_at_section caching_BOOST_LOG_BEFORE_INIT_CACHE_FILTER Cache messages before logs are initialized/ cache their filter as well (BOOST_LOG_BEFORE_INIT_CACHE_FILTER)
-It's a bit inefficient (after invoking the filter, it will always ask if cache is on or off). Also,
-it increases the application's size a bit - for each log statement, I will generate a callback that I can call later to see if the filter
-is still turned on or off.
+
+@section caching_BOOST_LOG_BEFORE_INIT_LOG_ALL Cache messages before logs are initialized regardless of their filter (BOOST_LOG_BEFORE_INIT_LOG_ALL)
+
+This case is the @b default. When cache is on, all messages are cached, regardless of their filter (as if all filters are turned on).
+Then, when cache is marked as initialized, all cached messages are logged.
+
+If you want to force this setting, make sure you define the @c BOOST_LOG_BEFORE_INIT_LOG_ALL globally (it's on by default anyway).
@code
...
#define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() )
...
-L_ << "this message will not be logged";
+L_ << "this message will be logged, even if filter will be turned off";
g_log_filter()->set_enabled(false);
g_l()->mark_as_initialized();
@endcode
-_at_section caching_BOOST_LOG_BEFORE_INIT_LOG_ALL Cache messages before logs are initialized regardless of their filter (BOOST_LOG_BEFORE_INIT_LOG_ALL)
-
-This case is the @b default. In the second case, when cache is on, all messages are cached, regardless of their filter (it's like all filters are on).
-Then, when cache is turned off, all messages are logged.
+\n
+@section caching_BOOST_LOG_BEFORE_INIT_CACHE_FILTER Cache messages before logs are initialized/ cache their filter as well (BOOST_LOG_BEFORE_INIT_CACHE_FILTER)
-If you do want to use this setting, make sure you define the @c BOOST_LOG_BEFORE_INIT_LOG_ALL globally.
+It's a bit inefficient (after invoking the filter, it will always ask if cache is on or off). Also,
+it increases the application's size a bit - for each log statement, I will generate a callback that I can call later to see if the filter
+is still turned on or off.
@code
...
#define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() )
...
-L_ << "this message will be logged, even if filter will be turned off";
+L_ << "this message will not be logged";
g_log_filter()->set_enabled(false);
g_l()->mark_as_initialized();
@endcode
+If you do want to use this setting, make sure you define the @c BOOST_LOG_BEFORE_INIT_CACHE_FILTER globally.
-_at_section caching_BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT Ignore all messages before turn_cache_off (BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT)
+@subsection caching_BOOST_LOG_BEFORE_INIT_CACHE_FILTER_the_catch BOOST_LOG_BEFORE_INIT_CACHE_FILTER - the catch...
-In the last case, all messages before @c turn_cache_off() are ignored.
+@note
+If you don't want to cache the filter, just skip to the @ref caching_BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT "next section".
-If you do want to use this setting, make sure you define the @c BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT globally.
+If you cache the filter as well, in order for the caching process to work, all the parameters you pass to the filter need to be:
+- either compile-time constants, or
+- global values
+Assume you have a logger with a filter based on levels:
@code
-...
-#define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() )
-...
+// for exposition only - normally you'd use BOOST_LOG_USE_LOG_IF_LEVEL
+#define L_(lvl) BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_level()->is_enabled( lvl ) )
+@endcode
-L_ << "this message will NOT be logged";
-g_l()->mark_as_initialized();
+If you cache the filter, the expression <tt>g_log_level()->is_enabled( lvl )</tt> needs to be recomputed at a later time
+(when the log is marked as initialized, and all messages that were cached, are logged).
+Thus, all parameters that are passed to the your L_ macro need to be either compile-time constants or global values. Otherwise, a compile-time error will
+be issued:
+
+@code
+void f() {
+ boost::logging::level lvl = ...;
+ // will generate a compile-time error : using a local variable as param
+ L_(lvl) << "wish it could work";
+}
@endcode
+Normally you should not care about this, since whatever you pass to your logging macros should indeed be constant.
+
-_at_section caching_ts Setting thread-safety of "is_cache_turned_on"
-In case you chose to use cache (either @c BOOST_LOG_BEFORE_INIT_CACHE_FILTER or @c BOOST_LOG_BEFORE_INIT_LOG_ALL), you can also set
-thread-safety of "is_cache_turned_on".
-Each time a message is logged, we need to ask : @c is_cache_turned_on. However, we also want to be as efficient as possible - we don't want
-this question to take too much CPU time. Thus, I came up with a simple algorithm:
-- first, query an @c is_enabled bool-like variable, which at the beginning is false (very efficient, we can use TSS here)
- - if this is true, it's clear that caching has been turned off
- - if this is false, we don't know for sure, thus, continue to ask
-- second, use a thread-safe "bool"-like variable (surrounded by a mutex, a bit slow, but that's life)
- - if this is true, we're still using cache
- - if this is false, caching has been turned off
- - set @c is_enabled to true
-
-Now, for the @c is_enabled variable, we can use several TSS tricks - like:
-- use @c ts_resource_single_thread (the default) - is_enabled is a simple bool variable. This is very efficient,
- and is perfect if for your logs, you call turn_cache_off() while there's a single thread running (thus, no concurrency issues).
-- use @c tss_resource_once_init - this resource, once initialized, it propagates through all threads.
-- use @c tss_resource_with_cache - each thread updates its value once at a certain period
+\n
+@section caching_BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT Ignore all messages before mark_as_initialized (BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT)
-There are several such policies, find them in the lock_resource_finder namespace.
+In the last case, all messages before @c mark_as_initialized() are ignored.
-If you want to override the above, make sure you define the @c BOOST_LOG_BEFORE_INIT_LOCK_RESOURCE_CLASS macro before including
-any Boost Logging Lib headers. Example:
+If you do want to use this setting, make sure you define the @c BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT globally.
@code
-#define BOOST_LOG_BEFORE_INIT_LOCK_RESOURCE_CLASS ::boost::logging::lock_resource_finder::tss_once_init<>
+...
+#define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() )
+...
+
+L_ << "this message will NOT be logged";
+g_l()->mark_as_initialized();
@endcode
+
+
+
*/
}}
Modified: sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -1,7 +1,9 @@
/**
@page page_changelog Changelog
-_at_section changelog_cur_ver Current Version: v0.21.6, 28 jan 2008
+@section changelog_cur_ver Current Version: v0.21.7, 30 jan 2008
+- updated docs : about caching/destruction
+- not using after_being_destroyed.hpp anymore - no need (see @ref after_destruction).
- made it much easier to include Boost Logging Lib headers: format_fwd.hpp, named_write_fwd.hpp, which internally accomodate for slow compilation
(that is, even if slow compile, you won't need to include more headers in your your_app_log.h file)
- updated docs + named_writer -> named_write
Modified: sandbox/logging/boost/logging/detail/raw_doc/defining_your_logger_filter.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/defining_your_logger_filter.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/defining_your_logger_filter.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -21,6 +21,7 @@
- @ref declare_define_use_macros_as_functions
- @ref declare_define_use_macros_fast_compile
- @ref declare_define_use_macros_before_main
+ - @ref declare_define_use_macros_no_after_destroyed
- @ref declare_define_manually
- @ref declare_define_manually_f_vs_v
- @ref declare_define_manually_logger_holder
@@ -280,6 +281,7 @@
-# cares about @ref BOOST_LOG_COMPILE_FAST_ON "Fast Compile" (default) or @ref BOOST_LOG_COMPILE_FAST_OFF "not"
-# ensures the logger/filter object is instantiated before @c main(), even if not used before main(). This is very useful,
since we can assume that before main() there won't be more than 1 threads, thus no problems at initializing the static variable.
+-# ensures we don't @ref after_destruction "use a logger and/or filter after it's been destroyed"
\n\n
@subsubsection declare_define_use_macros_as_functions logger/filter as functions
@@ -378,6 +380,7 @@
it forwards it to the real logger (implemented in logger_holder_by_value).
+
\n\n
@subsubsection declare_define_use_macros_before_main Ensuring instantiation before main()
@@ -393,6 +396,11 @@
+\n\n
+@subsubsection declare_define_use_macros_no_after_destroyed Ensuring you don't use a logger and/or filter after it's been destroyed
+
+See @ref after_destruction "this" for more details.
+
\n\n
Modified: sandbox/logging/boost/logging/detail/raw_doc/headers_to_include.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/headers_to_include.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/headers_to_include.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -35,7 +35,14 @@
#include <boost/logging/logging.hpp>
@endcode
-Note that these need to be included first, before any other Boost Logging Lib headers.
+
+- if in addition, if you want to do %logging on a dedicated thread
+
+@code
+// when you log messages on a dedicated thread (see writer::on_dedicated_thread class)
+#include <boost/logging/writer/on_dedicated_thread.hpp>
+@endcode
+
\n\n
@@ -58,9 +65,6 @@
@code
// when defining logs and you don't log messages on a dedicated thread
#include <boost/logging/format.hpp>
-
-// when defining logs and you log messages on a dedicated thread (see writer::on_dedicated_thread class)
-#include <boost/logging/format_ts.hpp>
@endcode
Modified: sandbox/logging/boost/logging/detail/raw_doc/table_of_contents.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/table_of_contents.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/table_of_contents.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -75,6 +75,8 @@
- @ref manipulator_generic
- @ref manipulator_create
- @ref manipulator_share_data
+ - @ref manipulator_manipulate "Modifying a formatter's state"
+ - @ref manipulator_manipulate "Modifying a destination's state"
- @ref formatter "Formatters"
- @ref destination "Destinations"
Modified: sandbox/logging/boost/logging/detail/raw_doc/todo.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/raw_doc/todo.hpp (original)
+++ sandbox/logging/boost/logging/detail/raw_doc/todo.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -22,14 +22,27 @@
@section todo_implementation Implementation
+- @c normal destination::stream_ptr - just like stream, but hold the stream as a shared pointer. Thus , we won't have to worry
+ about outliving the stream.
+
- @c normal on_dedicated_thead - remove dependency on boost::thread
+- @c normal on_dedicated_thead - I should see it I use logger::always_accurate increases logging time as opposed to some caching strategy.
+ I'm asking this because even if we were to use a critical section on the base_type writer's operator(), this will
+ *always* happen on the dedicated thread. Thus, I would think it should have very small overhead
+
+- @c high bug: if using named_writer on top of on_dedicated_thread writer, and I reset the format or destination strings,
+ I might end up modifying a formatter or destination, while some other thread is using it
+ perhaps it's not a bug - but pause()/resume() need to be called on it. Perhaps I can automate this!
+
- @c normal must have helper to call on on_destructed - like, to be able to write to cout,etc
- @c normal turn_cache_off() -> find better name, like mark_init_complete() (add a function named like this to call turn_cache_off()).
- @c normal have a logger_with_filter class, to make using the lib easier (this would hold the logger and the filter).
+- @c high destination::stream - have flush() and flush_each_time
+
- @c high writer::named_write<> need to allow tags by default, here!
- @c high scenario::use class - have ::gather and ::write typedefs !!!
@@ -158,7 +171,10 @@
- @c high explain about common_base()
+- @c high on_dedicated_thread : explain about manipulating it - while pause() TOTHINK if I can automate this
+- @c normal "Manipulating thy manipulator" - another way is to create another manipulator, delete the current one , and add the new one
+ i should explain that this could not work immediately because of caching.
*/
}}
Modified: sandbox/logging/boost/logging/detail/tags.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/tags.hpp (original)
+++ sandbox/logging/boost/logging/detail/tags.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -89,10 +89,10 @@
I can see a few issues with the above
- The context formatting is fixed
- - You can't choose at runtime - I want to see the level first, then the file & line
+ - You can't choose at runtime - what if I want to see the level first, then the file & line?
- You can't choose at runtime if you want to ignore some of that context (to speed up the app in some cases, you might decide not to log the file & line)
- You can't mix the context formatting with the rest of the formatting. For example, what if I want to log info like this : \n
- <tt>[idx] file_and_line [time] [level] message</tt> ?
+ <tt>[idx] file_and_line [time] message [level]</tt> ?
- You can't do extra formatting to any of the context. For example, when dumping file/line,
what if you want to strip some information from the file (the file name could be pretty big). Or, you might want to @em normalize
the file/line (like, fix it at 50 chars - by stripping or padding information)
Modified: sandbox/logging/boost/logging/format/destination/defaults.hpp
==============================================================================
--- sandbox/logging/boost/logging/format/destination/defaults.hpp (original)
+++ sandbox/logging/boost/logging/format/destination/defaults.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -64,6 +64,7 @@
/**
@brief writes to stream.
+ @note:
The stream must outlive this object! Or, clear() the stream, before the stream is deleted.
*/
template<class convert_dest = do_convert_destination > struct stream_t : is_generic, non_const_context< std::basic_ostream<boost::logging::char_type> * > {
Modified: sandbox/logging/boost/logging/gather/ostream_like.hpp
==============================================================================
--- sandbox/logging/boost/logging/gather/ostream_like.hpp (original)
+++ sandbox/logging/boost/logging/gather/ostream_like.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -33,8 +33,8 @@
A class that implements gathering the message needs 2 things:
- a function that will gather the data - called <tt>.out()</tt>
- define a function called <tt>.msg()</tt> that will return the gathered data (once all data has been gathered).
-- have a public type named "param" - be it a class or a typedef
- - this contains what the gather_msg class return
+- have a public type named "msg_type" - be it a class or a typedef
+ - this contains what the gather_msg class returns, as non-reference, non-const (that is, msg_type != const msg_type, "msg_type&" is a not a reference-to-reference)
*/
@@ -103,7 +103,6 @@
*/
template<class stream_type = std::basic_ostringstream<char_type> > struct return_raw_stream {
// what does the gather_msg class return?
-// typedef stream_type& param;
typedef stream_type msg_type;
return_raw_stream() {}
@@ -141,7 +140,6 @@
class stream_type = std::basic_ostringstream<char_type> > struct return_str {
// what does the gather_msg class return?
-// typedef string & param;
typedef string msg_type;
return_str() {}
@@ -163,7 +161,6 @@
*/
template<class holder_type, class stream_type> struct return_tag_holder : out_base {
// what does the gather_msg class return?
-// typedef holder_type& param;
typedef holder_type msg_type;
return_tag_holder() {}
Modified: sandbox/logging/boost/logging/writer/on_dedicated_thread.hpp
==============================================================================
--- sandbox/logging/boost/logging/writer/on_dedicated_thread.hpp (original)
+++ sandbox/logging/boost/logging/writer/on_dedicated_thread.hpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -36,11 +36,18 @@
namespace detail {
template<class msg_type> struct dedicated_thread_context {
- dedicated_thread_context() : is_working(true), write_period_ms(100) {}
+ dedicated_thread_context() : is_working(true), write_period_ms(100), is_paused(false), pause_acknowledged (false) {}
bool is_working;
int write_period_ms;
+ // if true, we've paused writing
+ // this is useful for when you want to manipulate the formatters/destinations
+ // (for instance, when you want to delete a destination)
+ bool is_paused;
+ // when true, the dedicated thread has acknowledged the pause
+ bool pause_acknowledged ;
+
boost::logging::threading::mutex cs;
// the thread doing the write
@@ -150,10 +157,63 @@
non_const_context_base::context().msgs.push_back(new_msg);
}
+
+ /** @brief Resumes the writes, after a pause()
+ */
+ void resume() {
+ scoped_lock lk( non_const_context_base::context().cs);
+ non_const_context_base::context().is_paused = false;
+ }
+
+ /** @brief Pauses the writes, so that you can manipulate the base object (the formatters/destinations, for instance)
+
+ After this function has been called, you can be @b sure that the other (dedicated) thread is not writing any messagges.
+ In other words, the other thread is not manipulating the base object (formatters/destinations, for instance), but you can do it.
+
+ FIXME allow a timeout as well
+ */
+ void pause() {
+ { scoped_lock lk( non_const_context_base::context().cs);
+ non_const_context_base::context().is_paused = true;
+ non_const_context_base::context().pause_acknowledged = false;
+ }
+
+ while ( true) {
+ do_sleep(10);
+ scoped_lock lk( non_const_context_base::context().cs);
+ if ( non_const_context_base::context().pause_acknowledged )
+ // the other thread has acknowledged
+ break;
+ }
+ }
private:
- void do_write() const {
+ static void do_sleep (int sleep_ms) {
const int NANOSECONDS_PER_SECOND = 1000 * 1000 * 1000;
+ boost::xtime to_wait;
+ xtime_get(&to_wait, boost::TIME_UTC);
+ to_wait.sec += sleep_ms / 1000;
+ to_wait.nsec += (sleep_ms % 1000) * (NANOSECONDS_PER_SECOND / 1000);
+ to_wait.sec += to_wait.nsec / NANOSECONDS_PER_SECOND ;
+ to_wait.nsec %= NANOSECONDS_PER_SECOND ;
+ boost::thread::sleep( to_wait);
+ }
+
+ // normally it sleeps for sleep_ms millisecs
+ // however, if we've been paused, it stops waiting
+ void wait_or_wake_up_on_pause(int sleep_ms) const {
+ int PERIOD = 100;
+ while ( sleep_ms > 0) {
+ do_sleep(sleep_ms > PERIOD ? PERIOD : sleep_ms);
+ sleep_ms -= PERIOD;
+
+ scoped_lock lk( non_const_context_base::context().cs);
+ if ( non_const_context_base::context().is_paused)
+ // this way we wake up early after we've been pause()d, even if sleep_ms has a high value
+ break;
+ }
+ }
+ void do_write() const {
int sleep_ms = 0;
while ( true) {
{ scoped_lock lk( non_const_context_base::context().cs);
@@ -162,16 +222,21 @@
if ( !non_const_context_base::context().is_working)
break; // we've been destroyed
}
+ wait_or_wake_up_on_pause(sleep_ms);
- boost::xtime to_wait;
- xtime_get(&to_wait, boost::TIME_UTC);
- to_wait.sec += sleep_ms / 1000;
- to_wait.nsec += (sleep_ms % 1000) * (NANOSECONDS_PER_SECOND / 1000);
- to_wait.sec += to_wait.nsec / NANOSECONDS_PER_SECOND ;
- to_wait.nsec %= NANOSECONDS_PER_SECOND ;
- boost::thread::sleep( to_wait);
-
+ { scoped_lock lk( non_const_context_base::context().cs);
+ if ( non_const_context_base::context().is_paused) {
+ // we're paused
+ non_const_context_base::context().pause_acknowledged = true;
+ continue;
+ }
+ }
write_array();
+ { scoped_lock lk( non_const_context_base::context().cs);
+ if ( non_const_context_base::context().is_paused)
+ // we're paused
+ non_const_context_base::context().pause_acknowledged = true;
+ }
}
}
Modified: sandbox/logging/lib/logging/internal/vc8/loggingvc8/test_now.cpp
==============================================================================
--- sandbox/logging/lib/logging/internal/vc8/loggingvc8/test_now.cpp (original)
+++ sandbox/logging/lib/logging/internal/vc8/loggingvc8/test_now.cpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -1,93 +1,96 @@
+#define BOOST_LOG_BEFORE_INIT_USE_CACHE_FILTER
-#define BOOST_LOG_COMPILE_FAST_OFF
-#include <boost/logging/format/named_write_fwd.hpp>
+// uncomment this, and all messages inside singleton's constructor will be logged!
+//#define BOOST_LOG_BEFORE_INIT_LOG_ALL
+// uncomment this, and NO messages inside singleton's constructor will be logged
+//#define BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT
-BOOST_LOG_FORMAT_MSG( optimize::cache_string_one_str<> )
-using namespace boost::logging;
+#include <boost/logging/format_fwd.hpp>
-typedef logger_format_write< default_, default_, writer::threading::no_ts > logger_type;
+BOOST_LOG_FORMAT_MSG( optimize::cache_string_one_str<> )
+#include <boost/logging/format.hpp>
-BOOST_DECLARE_LOG_FILTER(g_log_filter, filter::no_ts )
-BOOST_DECLARE_LOG(g_l, logger_type)
+typedef boost::logging::logger_format_write< > logger_type;
-#define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() )
-BOOST_DEFINE_LOG(g_l, logger_type)
-BOOST_DEFINE_LOG_FILTER(g_log_filter, filter::no_ts )
+BOOST_DECLARE_LOG_FILTER(g_log_level, boost::logging::level::holder ) // holds the application log level
+BOOST_DECLARE_LOG(g_log_err, logger_type)
+BOOST_DECLARE_LOG(g_log_app, logger_type)
+BOOST_DECLARE_LOG(g_log_dbg, logger_type)
+#define LDBG_ BOOST_LOG_USE_LOG_IF_LEVEL(g_log_dbg(), g_log_level(), debug ) << "[dbg] "
+#define LERR_ BOOST_LOG_USE_LOG_IF_LEVEL(g_log_err(), g_log_level(), error )
+#define LAPP_ BOOST_LOG_USE_LOG_IF_LEVEL(g_log_app(), g_log_level(), info ) << "[app] "
+BOOST_DEFINE_LOG_FILTER(g_log_level, boost::logging::level::holder )
+BOOST_DEFINE_LOG(g_log_err, logger_type)
+BOOST_DEFINE_LOG(g_log_app, logger_type)
+BOOST_DEFINE_LOG(g_log_dbg, logger_type)
-// Example of custom formatter:
-// dump the no. of seconds since start of program
-struct secs_since_start : formatter::class_<secs_since_start, formatter::implement_op_equal::no_context > {
- ::time_t m_start;
- secs_since_start() : m_start( ::time(0) ) {}
- void operator()(param str) const {
- ::time_t now = ::time(0);
- std::stringstream out;
- out << "+" << (int)(now-m_start) << "s ";
- str.prepend_string( out.str() );
- }
-};
+using namespace boost::logging;
-// Example of custom destination:
-// Dump each message as XML
-struct as_xml :
- destination::class_<as_xml, destination::implement_op_equal::has_context>,
- destination::non_const_context<std::ofstream> {
-
- std::string m_name;
- as_xml(const char* name) : non_const_context_base(name), m_name(name) {}
- void operator()(param str) const {
- context() << "<msg>" << str << "</msg>" << std::endl;
+struct singleton {
+ singleton() {
+ // note: these messages are written before logs are initialized
+ int i = 1;
+ LDBG_ << "this is so cool " << i++;
+ LDBG_ << "this is so cool again " << i++;
+ LERR_ << "first error " << i++;
+
+ std::string hello = "hello", world = "world";
+ LAPP_ << hello << ", " << world;
+
+ LAPP_ << "coolio " << i++;
+ LERR_ << "second error " << i++;
+ LDBG_ << "some debug message" << i++;
}
+} s_;
- bool operator==(const as_xml& other) const { return m_name == other.m_name; }
-};
-
-#if 0
-int main() {
- secs_since_start s;
- secs_since_start::raw_param a;
- std::cout << a;
+void init_logs() {
+ // Err log
+ g_log_err()->writer().add_formatter( formatter::idx(), "[%] " );
+ g_log_err()->writer().add_formatter( formatter::time("$hh:$mm.$ss ") );
+ g_log_err()->writer().add_formatter( formatter::append_newline() );
+ g_log_err()->writer().add_destination( destination::file("err.txt") );
+
+ destination::file out("out.txt");
+ // App log
+ g_log_app()->writer().add_formatter( formatter::time("$hh:$mm.$ss ") );
+ g_log_app()->writer().add_formatter( formatter::append_newline() );
+ g_log_app()->writer().add_destination( out );
+ g_log_app()->writer().add_destination( destination::cout() );
+
+ // Debug log
+ g_log_dbg()->writer().add_formatter( formatter::time("$hh:$mm.$ss ") );
+ g_log_dbg()->writer().add_formatter( formatter::append_newline() );
+ g_log_dbg()->writer().add_destination( out );
+ g_log_dbg()->writer().add_destination( destination::dbg_window() );
+
+ // if you change this, you'll get a different output (more or less verbose)
+ g_log_level()->set_enabled(level::info);
+
+ g_log_err()->mark_as_initialized();
+ g_log_app()->mark_as_initialized();
+ g_log_dbg()->mark_as_initialized();
}
-#endif
-
-#if 1
-void custom_fmt_dest_example() {
- // add formatters and destinations
- // That is, how the message is to be formatted and where should it be written to
- g_l()->writer().add_formatter( formatter::idx(), "[%] " );
- g_l()->writer().add_formatter( formatter::append_newline() );
- g_l()->writer().add_formatter( secs_since_start() );
-
- g_l()->writer().add_destination( destination::cout() );
- g_l()->writer().add_destination( destination::dbg_window() );
- g_l()->writer().add_destination( as_xml("out.txt") );
- g_l()->mark_as_initialized();
-
- int i = 1;
- L_ << "this is so cool " << i++;
- L_ << "this is so cool again " << i++;
-
- std::string hello = "hello", world = "world";
- L_ << hello << ", " << world;
-
- g_log_filter()->set_enabled(false);
- L_ << "this will not be written to the log";
- L_ << "this won't be written to the log";
- g_log_filter()->set_enabled(true);
- L_ << "good to be back ;) " << i++;
+void cache_before_init_example() {
+ init_logs();
+ int i = 10;
+ LAPP_ << "after logs have been initialized " << i++;
+ g_log_level()->set_enabled(level::debug);
+ LDBG_ << "some debug message after logs have been initialized " << i++;
}
+
int main() {
- custom_fmt_dest_example();
+ cache_before_init_example();
}
-#endif
+
// End of file
+
Modified: sandbox/logging/lib/logging/samples/scenarios/cache_before_init.cpp
==============================================================================
--- sandbox/logging/lib/logging/samples/scenarios/cache_before_init.cpp (original)
+++ sandbox/logging/lib/logging/samples/scenarios/cache_before_init.cpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -57,6 +57,7 @@
*/
+#define BOOST_LOG_BEFORE_INIT_USE_CACHE_FILTER
// uncomment this, and all messages inside singleton's constructor will be logged!
//#define BOOST_LOG_BEFORE_INIT_LOG_ALL
Modified: sandbox/logging/lib/logging/samples/starter/my_app_log.cpp
==============================================================================
--- sandbox/logging/lib/logging/samples/starter/my_app_log.cpp (original)
+++ sandbox/logging/lib/logging/samples/starter/my_app_log.cpp 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -3,9 +3,6 @@
#include <boost/logging/format.hpp>
#include <boost/logging/format/formatter/tags.hpp>
-// uncomment if you want to use do logging on a dedicated thread
-// #include <boost/logging/writer/on_dedicated_thread.hpp>
-
// uncomment if you're using Named Formatters and Destinations
// #include <boost/logging/format/named_write.hpp>
Modified: sandbox/logging/lib/logging/samples/starter/my_app_log.h
==============================================================================
--- sandbox/logging/lib/logging/samples/starter/my_app_log.h (original)
+++ sandbox/logging/lib/logging/samples/starter/my_app_log.h 2008-01-29 20:39:12 EST (Tue, 29 Jan 2008)
@@ -7,6 +7,10 @@
// uncomment if you're using Named Formatters and Destinations
//#include <boost/logging/format/named_write_fwd.hpp>
+// uncomment if you want to do logging on a dedicated thread
+// #include <boost/logging/writer/on_dedicated_thread.hpp>
+
+
namespace bl = boost::logging;
typedef bl::tag::holder<
// string class
@@ -17,12 +21,6 @@
// typedef bl::optimize::cache_string_one_str<> log_string_type;
BOOST_LOG_FORMAT_MSG( log_string_type )
-// if not compiling fast...
-#ifndef BOOST_LOG_COMPILE_FAST
-// uncomment if you want to do logging on a dedicated thread
-// #include <boost/logging/writer/on_dedicated_thread.hpp>
-#endif
-
using namespace boost::logging::scenario::usage;
typedef use<
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk