Boost logo

Boost-Commit :

From: john.groups_at_[hidden]
Date: 2008-01-21 13:15:17


Author: jtorjo
Date: 2008-01-21 13:15:16 EST (Mon, 21 Jan 2008)
New Revision: 42901
URL: http://svn.boost.org/trac/boost/changeset/42901

Log:
[logging]
v0.20.16, 21 jan 2008
- docs about using loggers/filters are they were destroyed
Added:
   sandbox/logging/boost/logging/detail/raw_doc/after_destruction.hpp (contents, props changed)
   sandbox/logging/boost/logging/detail/raw_doc/defining_logger_macros.hpp (contents, props changed)
Text files modified:
   sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp | 3 +
   sandbox/logging/boost/logging/detail/raw_doc/table_of_contents.hpp | 13 +++++++----
   sandbox/logging/boost/logging/detail/raw_doc/todo.hpp | 4 +++
   sandbox/logging/boost/logging/profile.hpp | 45 +++++++++++++++++++++++++++++++++++++++
   sandbox/logging/lib/logging/internal/vc8/loggingvc8/loggingvc8.vcproj | 8 +++++++
   5 files changed, 66 insertions(+), 7 deletions(-)

Added: sandbox/logging/boost/logging/detail/raw_doc/after_destruction.hpp
==============================================================================
--- (empty file)
+++ sandbox/logging/boost/logging/detail/raw_doc/after_destruction.hpp 2008-01-21 13:15:16 EST (Mon, 21 Jan 2008)
@@ -0,0 +1,112 @@
+namespace boost { namespace logging {
+
+/**
+@page after_destruction Using the logger(s)/filter(s) after they've been destroyed
+
+- @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
+
+
+
+\n\n
+@section after_destruction_can_happen Can this happen?
+
+The short answer : yes. How? The order of inialization between translation units is not defined, thus the same applies
+for destruction. The following can happen:
+- a global object is constructed @em before a logger
+- 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
+@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
+@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
+@subsection after_destruction_ignore Ignoring this case
+
+To ignore this issue altogether, define BOOST_LOG_AFTER_BEING_DESTROYED_IGNORE directive globally.
+
+
+\n\n
+@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.
+
+By default, this raw function does nothing. You can overwrite it:
+
+@code
+void call_after_log_destruction(const std::string& str) {
+ std::cout << str;
+}
+...
+
+g_l()->set_after_destroyed( call_after_log_destruction);
+@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
+@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.
+
+
+
+
+\n\n
+@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.
+
+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
+
+Or, you can simply leak the data members.
+
+The filter classes that come with this library are safe to use.
+
+
+
+*/
+
+}}

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-21 13:15:16 EST (Mon, 21 Jan 2008)
@@ -1,7 +1,8 @@
 /**
 @page page_changelog Changelog
 
-_at_section changelog_cur_ver Current Version: v0.20.14, 20 jan 2008
+@section changelog_cur_ver Current Version: v0.20.16, 21 jan 2008
+- docs about using loggers/filters are they were destroyed
 - more docs about @ref defining_your_logger_filter
 - added example using profiling, @ref common_scenario_profile "see it"
 - refactored finding the writer; added logger_to_writer class

Added: sandbox/logging/boost/logging/detail/raw_doc/defining_logger_macros.hpp
==============================================================================
--- (empty file)
+++ sandbox/logging/boost/logging/detail/raw_doc/defining_logger_macros.hpp 2008-01-21 13:15:16 EST (Mon, 21 Jan 2008)
@@ -0,0 +1,136 @@
+namespace boost { namespace logging {
+
+/**
+@page defining_logger_macros Defining macros to do logging
+
+Now that you've @ref defining_your_logger_filter "declared and defined your loggers/filters", it's time to log messages in code.
+
+You'll have to define macros to log messages in code. Such a macro needs to do the following:
+- first, see if logger is enabled
+ - if so, do log the message
+ - else, ignore the message completely
+
+To see if the logger is enabled, you'll use a filter. Note that you can reuse the same filter for multiple loggers, in case you want to.
+
+To define a macro to logmessages in code, I've provided these few macros to help you:
+-# BOOST_LOG_USE_LOG_IF_FILTER(logger, filter_is_enabled)
+-# BOOST_LOG_USE_LOG_IF_LEVEL(logger, filter, level)
+-# BOOST_LOG_USE_SIMPLE_LOG_IF_FILTER(logger, filter_is_enabled)
+
+The parameters are:
+- logger - a pointer to a logger you've declared
+- filter_is_enabled - how to determine if the filter is enabled.
+ - For simple filters this can be a simple <tt>filter()->is_enabled()</tt>
+ - More complex filters can be passed additional information (as you'll see below)
+ - As an example of filter that needs an extra argument, we have: \n
+ <tt>BOOST_LOG_USE_LOG_IF_LEVEL(l, holder, the_level) = BOOST_LOG_USE_LOG_IF_FILTER(l, holder->is_enabled(the_level)) </tt>
+- level - in case you have a filter based on level
+
+How you define your macros is up to you. Assuming you have a filter based on levels, you can:
+- either define an <tt>L_(level)</tt> macro, which will care about the level or,
+- define an <tt>L..._</tt> macro for each level you want (for instance, LDBG_, LAPP_, LERR_).
+
+Here's how you'd do each of the above:
+
+@code
+typedef logger_format_write< > logger_type;
+typedef level::holder filter_type;
+
+BOOST_DECLARE_LOG_FILTER(g_log_level, filter_type )
+BOOST_DECLARE_LOG(g_l, logger_type)
+
+// Example 1 - have one macro depending on one parameter
+#define L_(lvl) BOOST_LOG_USE_LOG_IF_LEVEL(g_l(), g_log_level(), lvl )
+
+
+// Example 2
+#define LDBG_ BOOST_LOG_USE_LOG_IF_LEVEL(g_l(), g_log_level(), debug )
+#define LERR_ BOOST_LOG_USE_LOG_IF_LEVEL(g_l(), g_log_level(), error )
+#define LAPP_ BOOST_LOG_USE_LOG_IF_LEVEL(g_l(), g_log_level(), info )
+
+@endcode
+
+\n
+Using it in code:
+
+@code
+// Example 1
+L_(debug) << "this is a debug message " << i++;
+L_(info) << "this is an info " << i++;
+L_(error) << "this is an error " << i++;
+
+
+
+// Example 2
+LDBG_ << "this is a debug message " << i++;
+LAPP_ << "this is an info " << i++;
+LERR_ << "this is an error " << i++;
+@endcode
+
+\n\n
+Another example. Assume you have a @c file_filter class, which filters based on file name (a file can be turned on or off):
+
+@code
+struct file_filter {
+ bool is_enabled(const char * file_name) const ;
+ // ...
+};
+@endcode
+
+In this case, the macro used to do logging would look like:
+
+@code
+typedef logger_format_write< > logger_type;
+typedef file_filter filter_type;
+
+BOOST_DECLARE_LOG_FILTER(g_log_filter, filter_type )
+BOOST_DECLARE_LOG(g_l, logger_type)
+
+#define L_ BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled(__FILE__) )
+@endcode
+
+\n
+Using it in code:
+
+@code
+L_ << "this is a message " << i++;
+L_ << "hello world";
+@endcode
+
+
+\n\n
+Another example. Assume you have a @c module_filter class, which filters based on module name (logging for a module can be turne on or off) :
+
+@code
+struct module_filter {
+ bool is_enabled(const char * module_name) const ;
+ // ...
+};
+@endcode
+
+
+In this case, the macro used to do logging would look like:
+
+@code
+typedef logger_format_write< > logger_type;
+typedef module_filter filter_type;
+
+BOOST_DECLARE_LOG_FILTER(g_log_filter, filter_type )
+BOOST_DECLARE_LOG(g_l, logger_type)
+
+#define L_(mod) BOOST_LOG_USE_LOG_IF_FILTER(g_l(), g_log_filter()->is_enabled(mod) )
+@endcode
+
+\n
+Using it in code:
+
+@code
+L_("chart") << "activex loaded";
+L_("connect") << "connecting to server";
+@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-21 13:15:16 EST (Mon, 21 Jan 2008)
@@ -33,22 +33,25 @@
     - @ref scenario_multiple_files
     - @ref starter_project
 
-- Tutorial
+\n
+- @b Tutorial
     - @ref headers_to_include "Headers to #include"
     - @ref defining_your_logger_filter
+ - @ref defining_logger_macros
     - @ref scenario::usage "Choose the best filter/logger class, based on your application's needs"
     - @ref scoped_logs
     - @ref tag "Using tags"
+ - @ref profile "Profiling - computing the time spent while logging"
 
- FIXME macros for logging/ profiling
-
- FIXME Special cases : after destruction
+\n
+- <b>Special cases</b>
+ - @ref caching
+ - @ref after_destruction
 
 \n\n
 Advanced concepts
 - @ref thread_safety
 - @ref misc_unicode
-- @ref caching
 - @ref macros
     - @ref macros_if_else_strategy
     - @ref macros_using

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-21 13:15:16 EST (Mon, 21 Jan 2008)
@@ -26,6 +26,10 @@
 
 - @c normal must have helper to call on on_destructed - like, to be able to write to cout,etc
 
+- @c high should see that if I have a tss* object, if used AFTER destruction, will not crash the application.
+ in other words, if I have tss_with_cache<int>, after this is destroyed, I should always reference the original int or so.
+ I need this when using a filter using TSS, after the filter has been destroyed.
+
 - @c high cut down compile time: make it compile faster (most likely improve use_format_write, etc)
 
 - @c high logger_format_write<> should be just like other find classes - have logger_format_write<>::type

Modified: sandbox/logging/boost/logging/profile.hpp
==============================================================================
--- sandbox/logging/boost/logging/profile.hpp (original)
+++ sandbox/logging/boost/logging/profile.hpp 2008-01-21 13:15:16 EST (Mon, 21 Jan 2008)
@@ -46,7 +46,50 @@
 
 /** @brief Allows profiling your application
 
-See compute_for_logger and compute_for_filter classes
+If you want to profile your application (find out how much time is spent logging), all you need to do is to surround your logger and filter class(es)
+by profile::compute_for_logger and with profile::compute_for_filter, like shown below:
+
+Your code:
+@code
+namespace bl = boost::logging;
+typedef bl::logger_format_write< > logger_type;
+typedef bl::filter::no_ts filter_type;
+@endcode
+
+
+Your code with profiling:
+@code
+// notice the extra include
+#include <boost/logging/profile.hpp>
+
+namespace bl = boost::logging;
+typedef bl::logger_format_write< > raw_logger_type;
+typedef bl::profile::compute_for_logger<raw_logger_type>::type logger_type;
+typedef bl::filter::no_ts raw_filter_type;
+typedef bl::profile::compute_for_filter<raw_filter_type>::type filter_type;
+@endcode
+
+In addition to the above, you'll need to set a place where to dump the profile information (which will be dumped at end of the program).
+This is just a functor that takes a <tt>const std::string&</tt> argument. Thus, it can be any destination class. For instance:
+
+@code
+// where shall the profile results be outputted?
+bl::profile::compute::inst().log_results( bl::destination::file("profile.txt") );
+@endcode
+
+\n
+Results can look like this:
+
+@code
+gather time: 5.562500 seconds
+write time: 5.265625 seconds
+filter time: 0.31250 seconds
+otherthread time: 0.0 seconds
+@endcode
+
+
+\n\n
+For more info, see compute_for_logger and compute_for_filter classes.
 */
 namespace profile {
 

Modified: sandbox/logging/lib/logging/internal/vc8/loggingvc8/loggingvc8.vcproj
==============================================================================
--- sandbox/logging/lib/logging/internal/vc8/loggingvc8/loggingvc8.vcproj (original)
+++ sandbox/logging/lib/logging/internal/vc8/loggingvc8/loggingvc8.vcproj 2008-01-21 13:15:16 EST (Mon, 21 Jan 2008)
@@ -718,6 +718,10 @@
>
                         </File>
                         <File
+ RelativePath="..\..\..\..\..\boost\logging\detail\raw_doc\after_destruction.hpp"
+ >
+ </File>
+ <File
                                 RelativePath="..\..\..\..\..\boost\logging\detail\raw_doc\breaking_changes.hpp"
>
                         </File>
@@ -734,6 +738,10 @@
>
                         </File>
                         <File
+ RelativePath="..\..\..\..\..\boost\logging\detail\raw_doc\defining_logger_macros.hpp"
+ >
+ </File>
+ <File
                                 RelativePath="..\..\..\..\..\boost\logging\detail\raw_doc\defining_your_logger_filter.hpp"
>
                         </File>


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