Boost logo

Boost-Commit :

From: john.groups_at_[hidden]
Date: 2007-10-18 07:12:57


Author: jtorjo
Date: 2007-10-18 07:12:56 EDT (Thu, 18 Oct 2007)
New Revision: 40150
URL: http://svn.boost.org/trac/boost/changeset/40150

Log:
[logging]
v0.7.2
- format_write cares if formatter/destination is generic or not
- solved bug when deleting manipulators (same_type needed to have a virtual destructor)

Text files modified:
   sandbox/logging/boost/logging/detail/manipulator.hpp | 70 ++++++++++++++++++++++++++++++++++-
   sandbox/logging/boost/logging/format/destination/shared_memory.hpp | 7 ++-
   sandbox/logging/boost/logging/format/op_equal.hpp | 5 ++
   sandbox/logging/boost/logging/format/optimize.hpp | 3 +
   sandbox/logging/boost/logging/writer/format_write.hpp | 79 ++++++++++++++++++++++++++++++++++-----
   sandbox/logging/lib/logging/tests/format/test_simple_formatter.cpp | 4 +-
   6 files changed, 151 insertions(+), 17 deletions(-)

Modified: sandbox/logging/boost/logging/detail/manipulator.hpp
==============================================================================
--- sandbox/logging/boost/logging/detail/manipulator.hpp (original)
+++ sandbox/logging/boost/logging/detail/manipulator.hpp 2007-10-18 07:12:56 EDT (Thu, 18 Oct 2007)
@@ -135,11 +135,13 @@
     
 All formatter or destination class need to directly or indirectly derive from this.
 
-All formatters need to derive from a common %base class.
+@section manipulator_base_class Manipulator base classes
+
+<b>All formatters need to derive from a common %base class.
 When dealing with formatters, the first thing you must do is to specify that common base class.
 All formatter classes will derive from it, directly or indirectly.
 
-Same goes for destinations.
+Same goes for destinations.</b>
 
 Note that the formatter base class and the destination base class don't need to be the same.
 
@@ -269,7 +271,61 @@
 
 
 
+/**
+@brief Represents a generic manipulator (formatter or destination)
+
+A generic manipulator is one that does not derive from any formatter_base or destination_base class (@ref manipulator_base_class).
+
+Libraries, such as this one, can provide generic manipulators, and they can't rely on
+any @ref manipulator_base_class "base class" - since it's you, the user, who can choose which is the base class.
 
+A generic manipulator has no way of knowing the type of the @em msg you pass on operator().
+Thus, usually generic manipulators have a templated operator=, and do the best to convert what's in, to what they need.
+
+Example:
+@code
+template<class convert_dest = do_convert_destination > struct cout {
+ template<class msg_type> void operator()(const msg_type & msg) const {
+ convert_dest::write(msg, std::cout);
+ }
+};
+@endcode
+
+As long as exists a conversion function from your @c msg_type to what the manipulator needs, it all works.
+Thus, no matter what your %formatter @ref manipulator_base_class "base class" or %destination @ref manipulator_base_class "base class"
+is, the code will still work. You can add your %formatter/ %destination classes, and the generic %formatter/ %destination classes
+
+@code
+typedef ... formatter_base;
+logger< format_write<...> > g_l;
+
+struct my_cool_formatter : formatter_base { ... };
+
+// adding formatter class from the Logging lib
+g_l.add_formatter( formatter::thread_id() );
+
+// adding formatter class defined by you
+g_l.add_formatter( my_cool_formatter() );
+@endcode
+
+@sa boost::logging::destination::convert, boost::logging::formatter::convert
+*/
+struct is_generic {};
+
+namespace detail {
+
+ // holds the generic manipulator, and forwards to it
+ template<class generic_type, class manipulator_base> struct generic_holder : manipulator_base {
+ typedef typename manipulator_base::param param;
+
+ generic_type m_val;
+ generic_holder(const generic_type & val) : m_val(val) {}
+
+ virtual void operator()(param val) const {
+ m_val.operator()(val);
+ }
+ };
+}
 
 
 
@@ -298,6 +354,11 @@
     using boost::logging::manipulator::base;
     using boost::logging::manipulator::base_no_operator_call;
     using boost::logging::manipulator::non_const_context;
+
+ /**
+ @sa boost::logging::manipulator::is_generic
+ */
+ typedef boost::logging::manipulator::is_generic is_generic;
 }
 
 /**
@@ -315,6 +376,11 @@
     using boost::logging::manipulator::base;
     using boost::logging::manipulator::base_no_operator_call;
     using boost::logging::manipulator::non_const_context;
+
+ /**
+ @sa boost::logging::manipulator::is_generic
+ */
+ typedef boost::logging::manipulator::is_generic is_generic;
 }
 
 }}

Modified: sandbox/logging/boost/logging/format/destination/shared_memory.hpp
==============================================================================
--- sandbox/logging/boost/logging/format/destination/shared_memory.hpp (original)
+++ sandbox/logging/boost/logging/format/destination/shared_memory.hpp 2007-10-18 07:12:56 EDT (Thu, 18 Oct 2007)
@@ -46,10 +46,13 @@
     };
 }
 
-template<class convert_dest = do_convert_destination > struct shared_memory {
+/**
+ @brief Logs the information in shared memory
+*/
+template<class convert_dest = do_convert_destination > struct shared_memory : non_const_context<detail::shared_memory_context> {
 
     enum { just_in_case = 8192 };
- basic_shared_memory_appender(const std::string & name, std::size_t mem_size = 2 * 1024 * 1024 * sizeof(char_type) ) : m_info(new info) {
+ basic_shared_memory_appender(const std::string & name, std::size_t mem_size = 2 * 1024 * 1024 * sizeof(char_type) ) {
         non_const_context_base::context().mem_size = mem_size;
         
         // this segment might have been previously created...

Modified: sandbox/logging/boost/logging/format/op_equal.hpp
==============================================================================
--- sandbox/logging/boost/logging/format/op_equal.hpp (original)
+++ sandbox/logging/boost/logging/format/op_equal.hpp 2007-10-18 07:12:56 EDT (Thu, 18 Oct 2007)
@@ -88,8 +88,11 @@
     protected:
         same_type() {}
         same_type(const same_type&) {}
+ virtual ~same_type() {}
     public:
- inline bool operator ==(const same_type& other) const { return typeid(*this) == typeid(other); }
+ inline bool operator ==(const same_type& other) const {
+ return typeid(*this) == typeid(other);
+ }
     };
 
 

Modified: sandbox/logging/boost/logging/format/optimize.hpp
==============================================================================
--- sandbox/logging/boost/logging/format/optimize.hpp (original)
+++ sandbox/logging/boost/logging/format/optimize.hpp 2007-10-18 07:12:56 EDT (Thu, 18 Oct 2007)
@@ -22,6 +22,9 @@
 
 #include <boost/logging/detail/fwd.hpp>
 #include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <vector>
 
 namespace boost { namespace logging {
 

Modified: sandbox/logging/boost/logging/writer/format_write.hpp
==============================================================================
--- sandbox/logging/boost/logging/writer/format_write.hpp (original)
+++ sandbox/logging/boost/logging/writer/format_write.hpp 2007-10-18 07:12:56 EDT (Thu, 18 Oct 2007)
@@ -22,6 +22,7 @@
 #endif
 
 #include <boost/logging/detail/fwd.hpp>
+#include <boost/type_traits/is_base_of.hpp>
 
 namespace boost { namespace logging {
 
@@ -126,38 +127,96 @@
 
     format_write() : m_router(m_formatters, m_destinations) {}
 
+
+private:
+
+ // non-generic
+ template<class formatter> void add_formatter_impl(formatter fmt, const boost::false_type& ) {
+ formatter_ptr p = m_formatters.append(fmt);
+ m_router.append_formatter(p);
+ }
+
+ // non-generic
+ template<class formatter> void del_formatter_impl(formatter fmt, const boost::false_type& ) {
+ formatter_ptr p = m_formatters.get_ptr(fmt);
+ m_router.del_formatter(p);
+ m_formatters.del(fmt);
+ }
+
+ // non-generic
+ template<class destination> void add_destination_impl(destination dest, const boost::false_type& ) {
+ destination_ptr p = m_destinations.append(dest);
+ m_router.append_destination(p);
+ }
+
+ // non-generic
+ template<class destination> void del_destination_impl(destination dest, const boost::false_type& ) {
+ destination_ptr p = m_destinations.get_ptr(dest);
+ m_router.del_destination(p);
+ m_destinations.del(dest);
+ }
+
+
+
+
+
+ // generic manipulator
+ template<class formatter> void add_formatter_impl(formatter fmt, const boost::true_type& ) {
+ typedef boost::logging::manipulator::detail::generic_holder<formatter,formatter_base> holder;
+ add_formatter_impl( holder(fmt), boost::false_type() );
+ }
+
+ // generic manipulator
+ template<class formatter> void del_formatter_impl(formatter fmt, const boost::true_type& ) {
+ typedef boost::logging::manipulator::detail::generic_holder<formatter,formatter_base> holder;
+ del_formatter_impl( holder(fmt) boost::false_type() );
+ }
+
+ // generic manipulator
+ template<class destination> void add_destination_impl(destination dest, const boost::true_type& ) {
+ typedef boost::logging::manipulator::detail::generic_holder<destination,destination_basee> holder;
+ add_destination_impl( holder(dest) boost::false_type() );
+ }
+
+ // generic manipulator
+ template<class destination> void del_destination_impl(destination dest, const boost::true_type& ) {
+ typedef boost::logging::manipulator::detail::generic_holder<destination,destination_basee> holder;
+ del_destination_impl( holder(dest) boost::false_type() );
+ }
+
+
+
+public:
     /**
         adds a formatter
     */
     template<class formatter> void add_formatter(formatter fmt) {
- formatter_ptr p = m_formatters.append(fmt);
- m_router.append_formatter(p);
+ typedef boost::logging::manipulator::is_generic is_generic;
+ add_formatter_impl<formatter>( fmt, boost::is_base_of<is_generic,formatter>() );
     }
 
     /**
         deletes a formatter
     */
     template<class formatter> void del_formatter(formatter fmt) {
- formatter_ptr p = m_formatters.get_ptr(fmt);
- m_router.del_formatter(p);
- m_formatters.del(fmt);
+ typedef boost::logging::manipulator::is_generic is_generic;
+ del_formatter_impl<formatter>( fmt, boost::is_base_of<is_generic,formatter>() );
     }
 
     /**
         adds a destination
     */
     template<class destination> void add_destination(destination dest) {
- destination_ptr p = m_destinations.append(dest);
- m_router.append_destination(p);
+ typedef boost::logging::manipulator::is_generic is_generic;
+ add_destination_impl<destination>( dest, boost::is_base_of<is_generic,destination>() );
     }
 
     /**
         deletes a destination
     */
     template<class destination> void del_destination(destination dest) {
- destination_ptr p = m_destinations.get_ptr(dest);
- m_router.del_destination(p);
- m_destinations.del(dest);
+ typedef boost::logging::manipulator::is_generic is_generic;
+ del_destination_impl<destination>( dest, boost::is_base_of<is_generic,destination>() );
     }
 
     /**

Modified: sandbox/logging/lib/logging/tests/format/test_simple_formatter.cpp
==============================================================================
--- sandbox/logging/lib/logging/tests/format/test_simple_formatter.cpp (original)
+++ sandbox/logging/lib/logging/tests/format/test_simple_formatter.cpp 2007-10-18 07:12:56 EDT (Thu, 18 Oct 2007)
@@ -127,8 +127,8 @@
     g_l->writer().del_destination( write_to_cout() );
 
     // will not be written to cout
- L_ << "must be prefixed by time , no enter " << i++;
- L_ << "must be prefixed by time , no enter " << i++;
+ L_ << "must be prefixed by time , no enter " << i++ << ";";
+ L_ << "must be prefixed by time , no enter " << i++ << ";";
 }
 
 #ifdef SINGLE_TEST


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