Boost logo

Boost-Commit :

From: john.groups_at_[hidden]
Date: 2008-01-18 20:15:29


Author: jtorjo
Date: 2008-01-18 20:15:28 EST (Fri, 18 Jan 2008)
New Revision: 42861
URL: http://svn.boost.org/trac/boost/changeset/42861

Log:
[logging]
v0.20.7, 18 jan 2008
- added test for using logger after it's been destroyed
- handle using logger after it's been destroyed
Text files modified:
   sandbox/logging/boost/logging/detail/after_being_destroyed.hpp | 16 ++-
   sandbox/logging/boost/logging/detail/log_keeper.hpp | 20 +---
   sandbox/logging/boost/logging/detail/logger.hpp | 7 +
   sandbox/logging/boost/logging/detail/logger_base.hpp | 34 +++++++-
   sandbox/logging/boost/logging/detail/macros.hpp | 53 ++++++++++---
   sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp | 5
   sandbox/logging/boost/logging/detail/raw_doc/todo.hpp | 5 +
   sandbox/logging/lib/logging/internal/vc8/loggingvc8/test_now.cpp | 152 ++++++++++++++++++++++++++++-----------
   sandbox/logging/lib/logging/tests/test_after_destroyed/test.cpp | 1
   9 files changed, 212 insertions(+), 81 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-18 20:15:28 EST (Fri, 18 Jan 2008)
@@ -54,11 +54,6 @@
         typedef typename destination::msg_type<T>::raw_type raw_type;
         typedef void (*after_destroyed_func)(const raw_type&) ;
 
-
- void set_after_destroyed(after_destroyed_func f) {
- m_after_being_destroyed = f;
- }
-
     protected:
         // default implementation - do nothing
         static void nothing(const raw_type&) {}
@@ -74,13 +69,24 @@
         }
     private:
         bool m_is_destroyed;
+ protected:
         after_destroyed_func m_after_being_destroyed;
     };
 
     template<class T = override> struct after_being_destroyed_none {
+ typedef typename destination::msg_type<T>::raw_type raw_type;
+ typedef void (*after_destroyed_func)(const raw_type&) ;
+
+ protected:
+ after_being_destroyed_none () : m_after_being_destroyed(0) {}
+
         static bool is_still_alive() { return true; }
         // never called
         template<class type> void call_after_destroyed(const type&) const {}
+
+ protected:
+ // never used, needed for set_after_destroyed
+ after_destroyed_func m_after_being_destroyed;
     };
 
     template<class T = override> struct after_being_destroyed

Modified: sandbox/logging/boost/logging/detail/log_keeper.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/log_keeper.hpp (original)
+++ sandbox/logging/boost/logging/detail/log_keeper.hpp 2008-01-18 20:15:28 EST (Fri, 18 Jan 2008)
@@ -43,22 +43,16 @@
     typedef typename use_default<gather_msg, typename ::boost::logging::detail::fast_compile_with_default_gather<dummy>::gather_msg > ::type gather_type;
     typedef logger<gather_type> logger_base_type;
 
- BOOST_LOGGING_FORWARD_CONSTRUCTOR_WITH_NEW_AND_INIT(log_holder, m_log, type, init)
- ~log_holder() {
- delete m_base;
- m_base = 0;
- delete m_log;
- m_log = 0;
- }
+ BOOST_LOGGING_FORWARD_CONSTRUCTOR_INIT(log_holder, m_log, init)
 
- const type* operator->() const { return m_log; }
- type* operator->() { return m_log; }
+ const type* operator->() const { return &m_log; }
+ type* operator->() { return &m_log; }
 
     /**
         in case you want to get the real log object
     */
- const type* get() const { return m_log; }
- type* get() { return m_log; }
+ const type* get() const { return &m_log; }
+ type* get() { return &m_log; }
 
 
     const logger_base_type * base() const { return m_base; }
@@ -68,10 +62,10 @@
     void init() {
         m_base = 0;
         typedef typename type::write_type write_type;
- m_base = new forward_to_logger<gather_type, write_type>(m_log);
+ m_base = m_log.common_base();
     }
 private:
- type * m_log;
+ type m_log;
     logger_base_type * m_base;
 };
 

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-18 20:15:28 EST (Fri, 18 Jan 2008)
@@ -195,6 +195,13 @@
             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);
         }

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-18 20:15:28 EST (Fri, 18 Jan 2008)
@@ -49,6 +49,11 @@
         */
         template<class cache_type> struct default_cache_keeper {
             default_cache_keeper() : m_is_cache_turned_off(false) {}
+ ~default_cache_keeper() {
+ // after we're destroyed, always consider the cache turned off
+ // (just in case someone is using the logger after it's been destroyed
+ m_is_cache_turned_off = true;
+ }
 
             /**
                 I've implemented this as a fast "is turned off" question.
@@ -59,7 +64,12 @@
                 if ( m_is_cache_turned_off)
                     return true;
 
- return cache().is_cache_turned_off();
+ if ( cache().is_cache_turned_off() ) {
+ m_is_cache_turned_off = true;
+ return true;
+ }
+ else
+ return false;
             }
 
             /** note: this call does not need to be very efficient, since the cache is used seldom,
@@ -70,7 +80,7 @@
             virtual const cache_type & cache() const { return m_cache; }
         private:
             cache_type m_cache;
- bool m_is_cache_turned_off;
+ mutable bool m_is_cache_turned_off;
         };
 
     }
@@ -79,13 +89,14 @@
     namespace detail {
         template<class gather_msg , class write_msg > struct common_base_holder {
             typedef typename detail::find_gather_if_default<gather_msg>::gather_type gather_type;
- typedef logger<gather_type, default_> common_base_type;
+ typedef logger<gather_msg, default_> common_base_type;
+
             /**
                 ... returns a base object - one that can be used to log messages, without having to know the full type of the log.
                     Thus, it can also be passed between a library and the application that uses it, and vice-versa.
             */
- const common_base_type* common_base() const { return m_base; }
- common_base_type* common_base() { return m_base; }
+ const common_base_type* common_base() const { return &m_base; }
+ common_base_type* common_base() { return &m_base; }
 
         protected:
             // a base object - one that can be used to log messages, without having to know the full type of the log.
@@ -112,6 +123,19 @@
         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);
+ }
 
     };
 

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-18 20:15:28 EST (Fri, 18 Jan 2008)
@@ -532,26 +532,53 @@
 // ****** Fast compile ******
 #define BOOST_DECLARE_LOG(name,type) ::boost::logging::log_holder< type > & name ();
 
-#define BOOST_DEFINE_LOG(name,type) ::boost::logging::log_holder< type > & name () \
- { static ::boost::logging::log_holder< 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::log_holder< type > & name () \
- { static ::boost::logging::log_holder< type > l ( args ); return l; } \
- 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) ::boost::logging::log_holder< type > & name () \
+ { static ::boost::logging::log_holder< type > *l = new ::boost::logging::log_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::log_holder< type > & name () \
+ { static ::boost::logging::log_holder< type > *l = new ::boost::logging::log_holder< type > ( args ); return *l; } \
+ namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( name () ); }
 
+#else
+
+ // don't leak
+ #define BOOST_DEFINE_LOG(name,type) ::boost::logging::log_holder< type > & name () \
+ { static ::boost::logging::log_holder< 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::log_holder< type > & name () \
+ { static ::boost::logging::log_holder< type > l ( args ); return l; } \
+ namespace { boost::logging::ensure_early_log_creation ensure_log_is_created_before_main ## name ( name () ); }
+#endif
 
 #else
+
 // don't compile fast
 #define BOOST_DECLARE_LOG(name,type) type* name ();
 
-#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 () ); }
+#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_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 () ); }
+ // 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
 
 #endif
 

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-18 20:15:28 EST (Fri, 18 Jan 2008)
@@ -1,8 +1,9 @@
 /**
 @page page_changelog Changelog
 
-_at_section changelog_cur_ver Current Version: v0.20.5, 18 jan 2008
-- handle using logger after it's been destroyed (partially)
+@section changelog_cur_ver Current Version: v0.20.7, 18 jan 2008
+- added test for using logger after it's been destroyed
+- handle using logger after it's been destroyed
 - simpler version of logger (derive from logger_base)
 - added dll_and_exe - show how you can use a logger that is defined in a DLL, and use it from an EXE
 - explained the breaking change in the docs

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-18 20:15:28 EST (Fri, 18 Jan 2008)
@@ -27,6 +27,11 @@
 - @c low in the same way I've created convert_to_base(), I can create a convert_to_top(), on top of which
                     I can create my own way to gather message, and then write it.
 
+- @c low when leaking/not leaking loggers/using after_destroyed - have a templated class that allows this
+ (only if users ask for it)
+ I could probably do a bit more about caching as well - however, in this case, I should allow
+ for macros to be visible in client code (for instance, if client wants BOOST_LOG_BEFORE_INIT_USE_CACHE_FILTER)
+
 - @c high What should I do if someone is trying to use the log after it's been destroyed?
 
 - @c high test TSS on vs2003 and gcc/pthreads \n

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-18 20:15:28 EST (Fri, 18 Jan 2008)
@@ -1,72 +1,138 @@
+/**
+@example mul_levels_mul_logers.cpp
+
+@copydoc mul_levels_mul_logers
+
+@page mul_levels_mul_logers mul_levels_mul_logers.cpp Example
+
+
+This usage:
+- You have multiple levels (in this example: debug < info < error)
+- You want to format the message before it's written
+ (in this example: prefix it by time, by index and append newline to it)
+- You have several loggers
+- Each logger has several log destinations
+
+Optimizations:
+- use a cache string (from optimize namespace), in order to make formatting the message faster
+
+Logs:
+- Error messages go into err.txt file
+ - formatting - prefix each message by time, index, and append newline
+- Info output goes to console, and a file called out.txt
+ - formatting - prefix each message by "[app]", time, and append newline
+- Debug messages go to the debug output window, and a file called out.txt
+ - formatting - prefix each message by "[dbg]", time, and append newline
+
+
+Here's how the output will look like:
+
+The debug output window:
+@code
+07:52.30 [dbg] this is so cool 1
+07:52.30 [dbg] this is so cool again 2
+@endcode
+
+
+The console:
+@code
+07:52.30 [app] hello, world
+07:52.30 [app] good to be back ;) 4
+@endcode
+
+
+The out.txt file:
+@code
+07:52.30 [dbg] this is so cool 1
+07:52.30 [dbg] this is so cool again 2
+07:52.30 [app] hello, world
+07:52.30 [app] good to be back ;) 4
+@endcode
+
+
+The err.txt file
+@code
+07:52.30 [1] first error 3
+07:52.30 [2] second error 5
+@endcode
+*/
+
+
 
-#define BOOST_LOG_BEFORE_INIT_IGNORE_BEFORE_INIT
 #include <boost/logging/format_fwd.hpp>
 
 // Step 1: Optimize : use a cache string, to make formatting the message faster
 BOOST_LOG_FORMAT_MSG( optimize::cache_string_one_str<> )
 
 #include <boost/logging/format.hpp>
-#include <boost/logging/format/destination/rolling_file.hpp>
-
-using namespace boost::logging;
 
 // Step 3 : Specify your logging class(es)
-typedef logger_format_write< > log_type;
+typedef boost::logging::logger_format_write< > log_type;
 
 
 // Step 4: declare which filters and loggers you'll use (usually in a header file)
-BOOST_DECLARE_LOG_FILTER(g_log_filter, filter::no_ts )
-BOOST_DECLARE_LOG(g_l, log_type)
+BOOST_DECLARE_LOG_FILTER(g_log_level, boost::logging::level::holder ) // holds the application log level
+BOOST_DECLARE_LOG(g_log_err, log_type)
+BOOST_DECLARE_LOG(g_log_app, log_type)
+BOOST_DECLARE_LOG(g_log_dbg, log_type)
 
 // Step 5: define the macros through which you'll log
-#define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() )
+#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] "
+
 
 // Step 6: Define the filters and loggers you'll use (usually in a source file)
-BOOST_DEFINE_LOG_FILTER(g_log_filter, filter::no_ts )
-BOOST_DEFINE_LOG(g_l, log_type)
+BOOST_DEFINE_LOG_FILTER(g_log_level, boost::logging::level::holder )
+BOOST_DEFINE_LOG(g_log_err, log_type)
+BOOST_DEFINE_LOG(g_log_app, log_type)
+BOOST_DEFINE_LOG(g_log_dbg, log_type)
 
-void f () {
-// BOOST_SCOPED_LOG_CTX(L_);// << "execution_pool::executor_defer_func(...)";
- L_ << "Executing component ";
-}
+using namespace boost::logging;
 
-void one_logger_one_filter_example() {
- forward_to_logger< default_, destination::cout > l;
- logger<default_> * ll = l.common_base();
+void mul_levels_mul_logers_example() {
     // Step 7: 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_if_needed() );
- g_l()->writer().add_destination( destination::file("out.txt") );
- g_l()->writer().add_destination( destination::cout() );
- g_l()->writer().add_destination( destination::dbg_window() );
-
-
- destination::rolling_file_settings settings;
- settings
- .file_count( 10 )
- .max_size_bytes( 5242880 )
- .flush_each_time(true);
- destination::rolling_file loggerFile( "test.txt", settings );
- g_l()->writer().add_destination( loggerFile );
-
- g_l()->turn_cache_off();
+ // 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() );
+
+ g_log_app()->turn_cache_off();
+ g_log_err()->turn_cache_off();
+ g_log_dbg()->turn_cache_off();
 
     // Step 8: use it...
     int i = 1;
- L_ << "this is so cool " << i++;
- L_ << "this is so cool again " << i++;
+ LDBG_ << "this is so cool " << i++;
+ LDBG_ << "this is so cool again " << i++;
+ LERR_ << "first error " << 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";
+ LAPP_ << hello << ", " << world;
 
- g_log_filter()->set_enabled(true);
- L_ << "good to be back ;) " << i++;
+ g_log_level()->set_enabled(level::error);
+ LDBG_ << "this will not be written anywhere";
+ LAPP_ << "this won't be written anywhere either";
+
+ g_log_level()->set_enabled(level::info);
+ LAPP_ << "good to be back ;) " << i++;
+ LERR_ << "second error " << i++;
 
     // Step 9 : Enjoy!
 }
@@ -75,7 +141,7 @@
 
 
 int main() {
- one_logger_one_filter_example();
+ mul_levels_mul_logers_example();
 }
 
 

Modified: sandbox/logging/lib/logging/tests/test_after_destroyed/test.cpp
==============================================================================
--- sandbox/logging/lib/logging/tests/test_after_destroyed/test.cpp (original)
+++ sandbox/logging/lib/logging/tests/test_after_destroyed/test.cpp 2008-01-18 20:15:28 EST (Fri, 18 Jan 2008)
@@ -36,6 +36,7 @@
 BOOST_DEFINE_LOG_FILTER(g_log_filter, filter::no_ts )
 BOOST_DEFINE_LOG(g_l, log_type)
 
+
 #define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled() )
 
 // whatever we log to the rolling file, we log here too (easy was to find out all the info that was logged)


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