Boost logo

Boost-Commit :

From: john.groups_at_[hidden]
Date: 2007-11-07 20:52:01


Author: jtorjo
Date: 2007-11-07 20:52:00 EST (Wed, 07 Nov 2007)
New Revision: 40917
URL: http://svn.boost.org/trac/boost/changeset/40917

Log:
[logging]
v0.10.11, 8 nov 2007
- added tss_resource_once_init and correspondent filter/logger class
- added scenario.hpp - not tested yet

Added:
   sandbox/logging/boost/logging/scenario.hpp (contents, props changed)
Text files modified:
   sandbox/logging/boost/logging/defaults.hpp | 2
   sandbox/logging/boost/logging/detail/raw_doc/changelog.hpp | 4 +
   sandbox/logging/boost/logging/detail/ts/ts_resource.hpp | 80 ++++++++++++++++++++++++++++++++++++++-
   sandbox/logging/boost/logging/filter.hpp | 26 +++++++++++--
   sandbox/logging/boost/logging/format_fwd.hpp | 3 +
   sandbox/logging/boost/logging/level.hpp | 21 +++++++++-
   sandbox/logging/lib/logging/internal/vc8/loggingvc8/loggingvc8.vcproj | 11 ++---
   7 files changed, 128 insertions(+), 19 deletions(-)

Modified: sandbox/logging/boost/logging/defaults.hpp
==============================================================================
--- sandbox/logging/boost/logging/defaults.hpp (original)
+++ sandbox/logging/boost/logging/defaults.hpp 2007-11-07 20:52:00 EST (Wed, 07 Nov 2007)
@@ -85,7 +85,7 @@
     namespace level {
         struct holder_no_ts ;
         struct holder_ts ;
- struct holder_tss_with_cache ;
+ template<int> struct holder_tss_with_cache ;
     }
 
     namespace locker {

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 2007-11-07 20:52:00 EST (Wed, 07 Nov 2007)
@@ -1,7 +1,9 @@
 /**
 @page page_changelog Changelog
 
-v0.10.10, 6 nov 2007
+v0.10.11, 8 nov 2007
+- added tss_resource_once_init and correspondent filter/logger class
+- added scenario.hpp - not tested yet
 - added and tested thread-safety (ts_write/on_dedicated_thread) for logger_format_write<>
 - added 2 more scenarios: ts_loger_one_filter.cpp and ded_loger_one_filter.cpp
 

Modified: sandbox/logging/boost/logging/detail/ts/ts_resource.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/ts/ts_resource.hpp (original)
+++ sandbox/logging/boost/logging/detail/ts/ts_resource.hpp 2007-11-07 20:52:00 EST (Wed, 07 Nov 2007)
@@ -27,6 +27,9 @@
 #include <boost/assert.hpp>
 
 namespace boost { namespace logging {
+
+
+
     
 /**
     @brief Contains implementations of locker objects. Such a locker can lock data for read or write.
@@ -117,7 +120,7 @@
         @sa default_cache_millis how many secs to cache the data. By default, 5
     */
     template<class type, int default_cache_secs = 5, class mutex = boost::logging::threading::mutex > struct tss_resource_with_cache {
- typedef tss_resource_with_cache<type, default_cache_secs> self_type;
+ typedef tss_resource_with_cache<type, default_cache_secs, mutex> self_type;
 
     private:
         struct value_and_time {
@@ -179,8 +182,6 @@
             const type* operator->() { return &use(); }
         };
 
-
-
     private:
         mutable tss_value<value_and_time> m_cache;
         type m_val;
@@ -188,6 +189,79 @@
         int m_cache_secs;
     };
 
+
+
+
+ /**
+ Locks a resource, and uses TSS.
+
+ The resource can be initialized once, at any time, no matter how many threads.
+ Once the resource is initialized (basically, someone used resource::write), that is <b>the final value</b>
+
+ All other threads will use and cached the initialized value.
+
+ @sa locker
+ @sa default_cache_millis how many secs to cache the data. By default, 5
+ */
+ template<class type, class mutex = boost::logging::threading::mutex > struct tss_resource_once_init {
+ typedef tss_resource_once_init<type, mutex> self_type;
+
+ private:
+ struct cached_value {
+ cached_value(const type & val = type() ) : val(val), is_cached(false) {}
+ type val;
+ bool is_cached;
+ };
+
+ public:
+ tss_resource_once_init(const type& val = type() ) : m_val(val), m_cache(val), m_initialized(false) {}
+
+ struct read;
+ struct write;
+ friend struct read;
+ friend struct write;
+
+ struct write {
+ type & val;
+ typename mutex::scoped_lock locker;
+ write(self_type & self) : val(self.m_val), locker(self.m_cs) {
+ self.m_initialized = true;
+ }
+ ~write() {
+ }
+
+ type & use() { return val ; }
+ type* operator->() { return &use(); }
+ };
+
+ struct read {
+ const type *val ;
+ read(const self_type & self) {
+ cached_value & cached = *(self.m_cache);
+ val = &cached.val;
+ if ( !cached.is_cached) {
+ mutex::scoped_lock lk(self.m_cs);
+ if ( self.m_initialized) {
+ cached.val = self.m_val;
+ cached.is_cached = true;
+ }
+ }
+ }
+ ~read() {
+ }
+
+ const type & use() { return *val ; }
+ const type* operator->() { return &use(); }
+ };
+
+ private:
+ type m_val;
+ mutable tss_value<cached_value> m_cache;
+ mutable mutex m_cs;
+ bool m_initialized;
+ };
+
+
 #endif
 
 }}}

Modified: sandbox/logging/boost/logging/filter.hpp
==============================================================================
--- sandbox/logging/boost/logging/filter.hpp (original)
+++ sandbox/logging/boost/logging/filter.hpp 2007-11-07 20:52:00 EST (Wed, 07 Nov 2007)
@@ -160,7 +160,7 @@
 #ifndef BOOST_LOG_NO_TSS
 
 /**
- Uses TLS (Thread Local Storage) to find out if a filter is enabled or not. It caches the current "is_enabled" on each thread.
+ Uses TSS (Thread Specific Storage) to find out if a filter is enabled or not. It caches the current "is_enabled" on each thread.
     Then, at a given period, it retrieves the real "is_enabled".
 
     @remarks
@@ -168,10 +168,10 @@
     Another implementation can be done, which could be faster - where you retrieve the "is_enabled" each X calls on a given thread
     (like, every 20 calls on a given thread)
 */
-struct use_tss_with_cache {
- typedef locker::tss_resource_with_cache<bool> data;
+template<int default_cache_secs = 5> struct use_tss_with_cache {
+ typedef locker::tss_resource_with_cache<bool,default_cache_secs> data;
 
- use_tss_with_cache(int cache_secs) : m_enabled(true, cache_secs) {}
+ use_tss_with_cache(int cache_secs = default_cache_secs) : m_enabled(true, cache_secs) {}
     bool is_enabled() const {
         data::read enabled(m_enabled);
         return enabled.use();
@@ -184,6 +184,24 @@
     data m_enabled;
 };
 
+
+struct use_tss_once_init {
+ typedef locker::tss_resource_once_init<bool> data;
+
+ use_tss_once_init() : m_enabled(true) {}
+ bool is_enabled() const {
+ data::read enabled(m_enabled);
+ return enabled.use();
+ }
+ void set_enabled(bool enabled) {
+ data::write cur(m_enabled);
+ cur.use() = enabled;
+ }
+private:
+ data m_enabled;
+};
+
+
 #endif // #ifndef BOOST_LOG_NO_TSS
 
 

Modified: sandbox/logging/boost/logging/format_fwd.hpp
==============================================================================
--- sandbox/logging/boost/logging/format_fwd.hpp (original)
+++ sandbox/logging/boost/logging/format_fwd.hpp 2007-11-07 20:52:00 EST (Wed, 07 Nov 2007)
@@ -75,5 +75,8 @@
 
 }}
 
+
+//#include <boost/logging/scenario.hpp>
+
 #endif
 

Modified: sandbox/logging/boost/logging/level.hpp
==============================================================================
--- sandbox/logging/boost/logging/level.hpp (original)
+++ sandbox/logging/boost/logging/level.hpp 2007-11-07 20:52:00 EST (Wed, 07 Nov 2007)
@@ -127,10 +127,10 @@
         Uses TLS (Thread Local Storage) to find out if a level is enabled or not. It caches the current "is_enabled" on each thread.
         Then, at a given period, it retrieves the real "level".
     */
- struct holder_tss_with_cache {
- typedef locker::tss_resource_with_cache<type> data;
+ template<int default_cache_secs = 5> struct holder_tss_with_cache {
+ typedef locker::tss_resource_with_cache<type, default_cache_secs> data;
 
- holder_tss_with_cache(int cache_millis, type default_level = enable_all) : m_level(default_level, cache_millis) {}
+ holder_tss_with_cache(int cache_secs = default_cache_secs, type default_level = enable_all) : m_level(default_level, cache_secs) {}
         bool is_enabled(type test_level) const {
             data::read cur_level(m_level);
             return test_level >= cur_level.use();
@@ -143,6 +143,21 @@
         data m_level;
     };
 
+ struct holder_tss_once_init {
+ typedef locker::tss_resource_once_init<type> data;
+
+ holder_tss_once_init(type default_level = enable_all) : m_level(default_level) {}
+ bool is_enabled(type test_level) const {
+ data::read cur_level(m_level);
+ return test_level >= cur_level.use();
+ }
+ void set_enabled(type level) {
+ data::write cur_level(m_level);
+ cur_level.use() = level;
+ }
+ private:
+ data m_level;
+ };
 #endif
 
 

Added: sandbox/logging/boost/logging/scenario.hpp
==============================================================================
--- (empty file)
+++ sandbox/logging/boost/logging/scenario.hpp 2007-11-07 20:52:00 EST (Wed, 07 Nov 2007)
@@ -0,0 +1,292 @@
+// Template.hpp
+
+// Boost Logging library
+//
+// Author: John Torjo, www.torjo.com
+//
+// Copyright (C) 2007 John Torjo (see www.torjo.com for email)
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org for updates, documentation, and revision history.
+// See http://www.torjo.com/log2/ for more details
+
+
+#ifndef JT28092007_TEMPLATE_HPP_DEFINED
+#define JT28092007_TEMPLATE_HPP_DEFINED
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/logging/detail/fwd.hpp>
+
+namespace boost { namespace logging {
+
+
+namespace filter {
+ template<int> struct use_tss_with_cache ;
+ struct no_ts ;
+ struct ts ;
+ struct use_tss_once_init ;
+};
+
+namespace level {
+ template<int> struct holder_tss_with_cache ;
+ struct holder_tss_once_init ;
+ struct holder_ts;
+ struct holder_no_ts ;
+}
+
+
+/**
+ @brief Use it when you have a specific scenario, and want the best logger/filter classes for the scenario. Check out scenario::usage
+*/
+namespace scenario {
+
+/**
+ @brief Find out the right logger/filter, based on how your application will use the loggers and filters
+
+ First, don't forget to \n <tt>use namespace boost::logging::scenario::usage;</tt>
+*/
+namespace usage {
+
+ /** @brief Filter usage settings : filter_::change and filter_::level
+ */
+ namespace filter_ {
+ /** @brief When does the filter change? */
+ namespace change {
+ /** @brief Optimize for %often %change. Does per-thread caching. At a given period, it re-synchronizes.
+
+ This is the default, for a multi-threaded application.
+
+ @param cache_period_secs At what period should we re-syncronize
+ */
+ template<int cache_period_secs = 5> struct often {};
+
+ /** @brief Set only once, when there's only one thread running - thus, you don't need to worry about thread-syncronizing */
+ struct set_once_when_one_thread {};
+
+ /** @brief Set only once, when there could be multiple thread running.
+
+ We automatically implement a strategy to check if the filter/logger has been initialized, and when it's done, we cache
+ the result on every thread */
+ struct set_once_when_multiple_threads {};
+
+ /** @brief This is always accurate. However, it's the slowest too.
+
+ In case of multiple threads, it always locks the logger/filter before accessing it.
+
+ Not recommended, you should usually go with another strategy (often, set_once_when_one_thread or set_once_when_multiple_threads)
+ */
+ struct always_accurate {};
+
+ /** @brief Single threading. It doesn't matter when/how %often the filter/logger changes.
+
+ This is the default, for a single-threaded application.
+ */
+ struct single_thread {};
+
+#ifdef BOOST_HAS_THREADS
+ typedef often<> default_;
+#else
+ typedef single_thread default_;
+#endif
+ };
+
+ /** @brief What's our "level" policy? */
+ namespace level {
+ /** @brief not using levels (default) */
+ struct no_levels {};
+ /** @brief using levels */
+ struct use_levels {};
+
+ typedef no_levels default_;
+ };
+ }
+
+ /** @brief Logger %usage settings : logger_::change and logger_::favor
+ */
+ namespace logger_ {
+ /** @brief When does the logger change, that is, how often do you manipulate it?
+
+ Note that using the log does not mean changing it.
+ Manipulation means invoking non-const functions on the logger, like
+ adding/removing formatters/destinations for instance.
+ */
+ namespace change {
+ /** @brief Optimize for often change. Does per-thread caching. At a given period, it re-synchronizes.
+
+ This is the default, for a multi-threaded application.
+
+ @param cache_period_secs At what period should we re-syncronize
+ */
+ template<int cache_period_secs = 5> struct often {};
+
+ /** @brief Set only once, when there's only one thread running - thus, you don't need to worry about thread-syncronizing */
+ struct set_once_when_one_thread {};
+
+ /** @brief Set only once, when there could be multiple thread running.
+
+ We automatically implement a strategy to check if the filter/logger has been initialized, and when it's done, we cache
+ the result on every thread */
+ struct set_once_when_multiple_threads {};
+
+ /** @brief This is always accurate. However, it's the slowest too.
+
+ In case of multiple threads, it always locks the logger/filter before accessing it.
+
+ Not recommended, you should usually go with another strategy (often, set_once_when_one_thread or set_once_when_multiple_threads)
+ */
+ struct always_accurate {};
+
+ /** @brief Single threading. It doesn't matter when/how often the filter/logger changes.
+
+ This is the default, for a single-threaded application.
+ */
+ struct single_thread {};
+
+#ifdef BOOST_HAS_THREADS
+ typedef often<> default_;
+#else
+ typedef single_thread default_;
+#endif
+ };
+
+ /** @brief When logging, what should we %favor? */
+ namespace favor {
+ /** @brief This will favor speed (logging will happen on a dedicated thread). The only problem you could have is if the application crashes.
+
+ In this case, on Windows, the rest of the application will continue, and any non-flushed log message will be flushed.
+
+ On POSIX, this may not be the case.
+ */
+ struct speed {};
+
+ /** @brief all messages will be logged
+
+ This is the default
+ */
+ struct correctness {};
+
+ typedef correctness default_;
+ };
+ }
+
+
+
+ namespace detail_find_filter {
+ namespace level = ::boost::logging::scenario::usage::filter_::level;
+ namespace change = ::boost::logging::scenario::usage::filter_::change;
+
+ //////// use levels
+
+ template<class change_> struct find_filter_use_levels {};
+
+ template<int period_ms> struct find_filter_use_levels< change::often<period_ms> > {
+ typedef ::boost::logging::level::holder_tss_with_cache<period_ms> type;
+ };
+
+ template<> struct find_filter_use_levels< change::set_once_when_one_thread > {
+ typedef ::boost::logging::level::holder_no_ts type;
+ };
+
+ template<> struct find_filter_use_levels< change::set_once_when_multiple_threads > {
+ typedef ::boost::logging::level::holder_tss_once_init type;
+ };
+
+ template<> struct find_filter_use_levels< change::always_accurate > {
+ typedef ::boost::logging::level::holder_ts type;
+ };
+
+ template<> struct find_filter_use_levels< change::single_thread > {
+ typedef ::boost::logging::level::holder_no_ts type;
+ };
+
+
+
+ //////// no levels
+
+ template<class change_> struct find_filter_no_levels {};
+
+ template<int period_ms> struct find_filter_no_levels< change::often<period_ms> > {
+ typedef ::boost::logging::filter::use_tss_with_cache<period_ms> type;
+ };
+
+ template<> struct find_filter_no_levels< change::set_once_when_one_thread > {
+ typedef ::boost::logging::filter::no_ts type;
+ };
+
+ template<> struct find_filter_no_levels< change::set_once_when_multiple_threads > {
+ typedef ::boost::logging::filter::use_tss_once_init type;
+ };
+
+ template<> struct find_filter_no_levels< change::always_accurate > {
+ typedef ::boost::logging::filter::ts type;
+ };
+
+ template<> struct find_filter_no_levels< change::single_thread > {
+ typedef ::boost::logging::filter::no_ts type;
+ };
+
+
+
+ template<class change_, class level_> struct find_filter {
+ // no levels
+ typedef typename find_filter_no_levels<change_>::type type;
+ };
+
+ template<class change_> struct find_filter<change_, level::use_levels> {
+ typedef typename find_filter_use_levels<change_>::type type;
+ };
+
+ }
+
+
+ namespace detail_find_logger {
+ namespace favor = ::boost::logging::scenario::usage::logger_::favor;
+ namespace change = ::boost::logging::scenario::usage::logger_::change;
+ }
+
+ /**
+ @brief Finds a filter class and a logger class, based on your specific scenario
+
+ @param filter_change (optional) How does the %filter change? Any of the classes in the filter_::change namespace
+ @param filter_level_ (optional) Does our %filter %use levels? Any of the classes in the filter_::level namespace
+ @param logger_change (optional) How does our %logger change? Any of the classes in the logger_::change namespace
+ @param logger_favor (optional) What does the %logger favor? Any of the classes in the logger_::favor namespace
+ */
+ template<
+ class filter_change = default_,
+ class filter_level = default_,
+ class logger_change = default_,
+ class logger_favor = default_>
+ struct use {
+
+ typedef typename use_default<filter_change, filter_::change::default_ >::type filter_change_type;
+ typedef typename use_default<filter_level, filter_::level::default_ >::type filter_level_type;
+
+ typedef typename detail_find_filter::find_filter<filter_change_type, filter_level_type>::type filter;
+
+
+// typedef ... logger;
+ // typedef ... filter;
+ };
+}
+
+/**
+ @brief Find out the right logger/filter, based on thread-safety of logger(s)/filter(s)
+
+ First, don't forget to <tt>use namespace boost::logging::scenario::ts;</tt>
+*/
+namespace ts {
+}
+
+}
+
+}}
+
+#endif
+

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 2007-11-07 20:52:00 EST (Wed, 07 Nov 2007)
@@ -630,6 +630,10 @@
>
                         </File>
                         <File
+ RelativePath="..\..\..\..\..\boost\logging\scenario.hpp"
+ >
+ </File>
+ <File
                                 RelativePath="..\..\..\..\..\boost\logging\detail\sink.hpp"
>
                         </File>
@@ -996,13 +1000,6 @@
                         <File
                                 RelativePath="..\..\..\samples\scenarios\ts_loger_one_filter.cpp"
>
- <FileConfiguration
- Name="Test|Win32"
- >
- <Tool
- Name="VCCLCompilerTool"
- />
- </FileConfiguration>
                         </File>
                 </Filter>
         </Files>


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