$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r50579 - in sandbox/thread_safe_signals/trunk: boost/signals2 boost/signals2/detail libs/signals2/doc libs/signals2/doc/reference libs/signals2/test
From: fmhess_at_[hidden]
Date: 2009-01-14 11:58:31
Author: fmhess
Date: 2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
New Revision: 50579
URL: http://svn.boost.org/trac/boost/changeset/50579
Log:
Brought back trackable class, to ease porting of existing
single-threaded code from Boost.Signals to Boost.Signals2.
Added:
   sandbox/thread_safe_signals/trunk/boost/signals2/detail/tracked_objects_visitor.hpp   (contents, props changed)
   sandbox/thread_safe_signals/trunk/boost/signals2/trackable.hpp   (contents, props changed)
   sandbox/thread_safe_signals/trunk/libs/signals2/test/trackable_test.cpp   (contents, props changed)
Text files modified: 
   sandbox/thread_safe_signals/trunk/boost/signals2/connection.hpp             |     1 -                                       
   sandbox/thread_safe_signals/trunk/boost/signals2/detail/slot_template.hpp   |    19 ++++++++++++++-----                     
   sandbox/thread_safe_signals/trunk/boost/signals2/slot.hpp                   |    25 ++-----------------------               
   sandbox/thread_safe_signals/trunk/boost/signals2/slot_base.hpp              |     7 +++++++                                 
   sandbox/thread_safe_signals/trunk/libs/signals2/doc/Makefile                |     4 ++--                                    
   sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/reference.xml |     1 +                                       
   sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/trackable.xml |    28 +++++++++++++++++++++-------            
   7 files changed, 47 insertions(+), 38 deletions(-)
Modified: sandbox/thread_safe_signals/trunk/boost/signals2/connection.hpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/boost/signals2/connection.hpp	(original)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/connection.hpp	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -22,7 +22,6 @@
 #include <boost/signals2/detail/unique_lock.hpp>
 #include <boost/signals2/slot.hpp>
 #include <boost/type_traits.hpp>
-#include <boost/visit_each.hpp>
 #include <boost/weak_ptr.hpp>
 
 namespace boost
Modified: sandbox/thread_safe_signals/trunk/boost/signals2/detail/slot_template.hpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/boost/signals2/detail/slot_template.hpp	(original)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/detail/slot_template.hpp	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -44,9 +44,9 @@
       BOOST_STATIC_CONSTANT(int, arity = BOOST_SIGNALS2_NUM_ARGS);
 
       template<typename F>
-      BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const F& f): _slot_function(detail::get_invocable_slot(f, detail::tag_type(f)))
+      BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const F& f)
       {
-        detail::auto_tracker<typename detail::get_slot_tag<typename unwrap_reference<F>::type>::type> at(this, f);
+        init_slot_function(f);
       }
       // copy constructors
       template<BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS, Other), typename OtherSlotFunction>
@@ -67,9 +67,10 @@
 // template<typename Func, typename ArgType0, typename ArgType1, ..., typename ArgTypen-1> slotN(...
 #define BOOST_SIGNALS2_SLOT_BINDING_CONSTRUCTOR(z, n, data) \
       template<typename Func, BOOST_PP_ENUM_PARAMS(n, typename ArgType)> \
-      BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const Func &func,  BOOST_PP_ENUM(n, BOOST_SIGNALS2_SLOT_BINDING_ARG_DECL, ~)): \
-        _slot_function(bind(func, BOOST_PP_ENUM_PARAMS(n, arg))) \
-      {}
+      BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const Func &func,  BOOST_PP_ENUM(n, BOOST_SIGNALS2_SLOT_BINDING_ARG_DECL, ~)) \
+      { \
+        init_slot_function(bind(func, BOOST_PP_ENUM_PARAMS(n, arg))); \
+      }
 #define BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS 10
       BOOST_PP_REPEAT_FROM_TO(1, BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS, BOOST_SIGNALS2_SLOT_BINDING_CONSTRUCTOR, ~)
 #undef BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS
@@ -110,6 +111,14 @@
       const slot_function_type& slot_function() const {return _slot_function;}
       slot_function_type& slot_function() {return _slot_function;}
     private:
+      template<typename F>
+      void init_slot_function(const F& f)
+      {
+        _slot_function = detail::get_invocable_slot(f, detail::tag_type(f));
+        signals2::detail::tracked_objects_visitor visitor(this);
+        boost::visit_each(visitor, f);
+      }
+
       SlotFunction _slot_function;
     };
 
Added: sandbox/thread_safe_signals/trunk/boost/signals2/detail/tracked_objects_visitor.hpp
==============================================================================
--- (empty file)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/detail/tracked_objects_visitor.hpp	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -0,0 +1,96 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007-2008.
+// Copyright Timmo Stange 2007.
+// Copyright Douglas Gregor 2001-2004. Use, modification and
+// distribution is subject to 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)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP
+#define BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <boost/ref.hpp>
+#include <boost/signals2/detail/signals_common.hpp>
+#include <boost/signals2/slot_base.hpp>
+#include <boost/signals2/trackable.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/utility/addressof.hpp>
+
+namespace boost
+{
+  namespace signals2
+  {
+    namespace detail
+    {
+      // Visitor to collect tracked objects from a bound function.
+      class tracked_objects_visitor
+      {
+      public:
+        tracked_objects_visitor(slot_base *slot) : slot_(slot)
+        {}
+        template<typename T>
+        void operator()(const T& t) const
+        {
+            m_visit_reference_wrapper(t, mpl::bool_<is_reference_wrapper<T>::value>());
+        }
+      private:
+        template<typename T>
+        void m_visit_reference_wrapper(const reference_wrapper<T> &t, const mpl::bool_<true> &) const
+        {
+            m_visit_pointer(t.get_pointer(), mpl::bool_<true>());
+        }
+        template<typename T>
+        void m_visit_reference_wrapper(const T &t, const mpl::bool_<false> &) const
+        {
+            m_visit_pointer(t, mpl::bool_<is_pointer<T>::value>());
+        }
+        template<typename T>
+        void m_visit_pointer(const T &t, const mpl::bool_<true> &) const
+        {
+            m_visit_not_function_pointer(t, mpl::bool_<is_convertible<T, const void*>::value>());
+        }
+        template<typename T>
+        void m_visit_pointer(const T &t, const mpl::bool_<false> &) const
+        {
+            m_visit_pointer(addressof(t), mpl::bool_<true>());
+        }
+        template<typename T>
+        void m_visit_not_function_pointer(const T *t, const mpl::bool_<true> &) const
+        {
+            m_visit_signal(t, mpl::bool_<is_signal<T>::value>());
+        }
+        template<typename T>
+        void m_visit_not_function_pointer(const T &t, const mpl::bool_<false> &) const
+        {}
+        template<typename T>
+        void m_visit_signal(const T *signal, const mpl::bool_<true> &) const
+        {
+          if(signal)
+            slot_->track_signal(*signal);
+        }
+        template<typename T>
+        void m_visit_signal(const T &t, const mpl::bool_<false> &) const
+        {
+            add_if_trackable(t);
+        }
+        void add_if_trackable(const trackable *trackable) const
+        {
+          if(trackable)
+            slot_->_tracked_objects.push_back(trackable->get_shared_ptr());
+        }
+        void add_if_trackable(const void *trackable) const {}
+
+        mutable slot_base * slot_;
+      };
+
+
+    } // end namespace detail
+  } // end namespace signals2
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP
+
Modified: sandbox/thread_safe_signals/trunk/boost/signals2/slot.hpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/boost/signals2/slot.hpp	(original)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/slot.hpp	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -14,16 +14,15 @@
 
 #include <boost/bind.hpp>
 #include <boost/function.hpp>
-#include <boost/mpl/bool.hpp>
 #include <boost/preprocessor/repetition.hpp>
 #include <boost/ref.hpp>
 #include <boost/signals2/detail/signals_common.hpp>
 #include <boost/signals2/detail/signals_common_macros.hpp>
+#include <boost/signals2/detail/tracked_objects_visitor.hpp>
 #include <boost/signals2/slot_base.hpp>
 #include <boost/type_traits.hpp>
-#include <boost/utility/addressof.hpp>
+#include <boost/visit_each.hpp>
 #include <boost/weak_ptr.hpp>
-#include <vector>
 
 namespace boost
 {
@@ -58,26 +57,6 @@
         the_tag_type tag = the_tag_type();
         return tag;
       }
-
-      // used to automatically track signal objects that are passed directly to slots
-      template<typename SlotTag>
-      class auto_tracker
-      {
-      public:
-        template<typename Slot, typename F>
-          auto_tracker(Slot *slot, const F &f)
-        {}
-      };
-      template<>
-      class auto_tracker<signal_tag>
-      {
-      public:
-        template<typename Slot, typename F>
-          auto_tracker(Slot *slot, const F &f)
-        {
-          slot->track(f);
-        }
-      };
     }
   }
 } // end namespace boost
Modified: sandbox/thread_safe_signals/trunk/boost/signals2/slot_base.hpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/boost/signals2/slot_base.hpp	(original)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/slot_base.hpp	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -22,6 +22,11 @@
 {
   namespace signals2
   {
+    namespace detail
+    {
+      class tracked_objects_visitor;
+    }
+
     class expired_slot: public bad_weak_ptr
     {
     public:
@@ -65,6 +70,8 @@
         return false;
       }
     protected:
+      friend class detail::tracked_objects_visitor;
+
       void track_signal(const signal_base &signal)
       {
         _tracked_objects.push_back(signal.lock_pimpl());
Added: sandbox/thread_safe_signals/trunk/boost/signals2/trackable.hpp
==============================================================================
--- (empty file)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/trackable.hpp	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -0,0 +1,49 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007,2009.
+// Copyright Timmo Stange 2007.
+// Copyright Douglas Gregor 2001-2004. Use, modification and
+// distribution is subject to 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)
+
+// Compatibility class to ease porting from the original
+// Boost.Signals library.  However,
+// boost::signals2::trackable is NOT thread-safe.
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_TRACKABLE_HPP
+#define BOOST_SIGNALS2_TRACKABLE_HPP
+
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace boost {
+  namespace signals2 {
+    namespace detail
+    {
+        class tracked_objects_visitor;
+    }
+    class trackable {
+    protected:
+      trackable(): _tracked_ptr(static_cast<int*>(0)) {}
+      trackable(const trackable &): _tracked_ptr(static_cast<int*>(0)) {}
+      trackable& operator=(const trackable &)
+      {
+          return *this;
+      }
+      ~trackable() {}
+    private:
+      friend class detail::tracked_objects_visitor;
+      const shared_ptr<void>& get_shared_ptr() const
+      {
+          return _tracked_ptr;
+      }
+
+      shared_ptr<void> _tracked_ptr;
+    };
+  } // end namespace signals2
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_TRACKABLE_HPP
Modified: sandbox/thread_safe_signals/trunk/libs/signals2/doc/Makefile
==============================================================================
--- sandbox/thread_safe_signals/trunk/libs/signals2/doc/Makefile	(original)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/doc/Makefile	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -24,8 +24,8 @@
         reference/signal_base.xml \
         reference/signal_header.xml \
         reference/slot_base.xml \
-	reference/slot.xml
-#	reference/trackable.xml \
+	reference/slot.xml \
+	reference/trackable.xml \
 #	reference/visit_each.xml
 
 .PHONY: all
Modified: sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/reference.xml
==============================================================================
--- sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/reference.xml	(original)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/reference.xml	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -23,4 +23,5 @@
   <xi:include href="signal_base.xml"/>
   <xi:include href="slot.xml"/>
   <xi:include href="slot_base.xml"/>
+  <xi:include href="trackable.xml"/>
 </library-reference>
Modified: sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/trackable.xml
==============================================================================
--- sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/trackable.xml	(original)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/doc/reference/trackable.xml	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -1,17 +1,30 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE header PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
   "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<header name="boost/signals/trackable.hpp">
+<header name="boost/signals2/trackable.hpp">
   <namespace name="boost">
-    <namespace name="signals">
+    <namespace name="signals2">
       <class name="trackable">
-        <purpose><emphasis role="bold">DEPRECATED</emphasis>.  Enables safe use of multicast callbacks.</purpose>
+        <purpose>Provided to ease porting for code using the boost::signals::trackable class from
+          the original Boost.Signals library.</purpose>
 
         <description>
-          <para>The <code>trackable</code> class has
-          been deprecated in favor of <code>shared_ptr</code>s and
-          <functionname>track</functionname> because <code>trackable</code>
-          cannot be made thread-safe.</para>
+          <para>Use of the <code>trackable</code> class is not recommended
+          for new code.  The <code>trackable</code> class is not thread-safe
+          since <code>trackable</code> objects disconnect their associated
+          connections in the <code>trackable</code> destructor.
+          The <code>trackable</code> destructor is not run until
+          after the destructors of any derived classes have completed,
+          which leaves a window where a partially destructed
+          object can still have active connections.
+          </para>
+
+          <para>
+          The preferred method of automatic connection management
+          with Boost.Signals2 is to manage the lifetime of
+          tracked objects with <code>shared_ptr</code>s and
+          to use the <methodname alt="slotN::track">slot::track</methodname>
+          method to track their lifetimes.</para>
 
           <para>The <code>trackable</code> class provides automatic
           disconnection of signals and slots when objects bound in
@@ -28,6 +41,7 @@
           <functionname>visit_each</functionname> overloads for any
           type that may contain pointers or references to trackable
           objects.</para>
+
         </description>
 
         <constructor>
Added: sandbox/thread_safe_signals/trunk/libs/signals2/test/trackable_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/test/trackable_test.cpp	2009-01-14 11:58:30 EST (Wed, 14 Jan 2009)
@@ -0,0 +1,75 @@
+// Boost.Signals2 library
+
+// Copyright Douglas Gregor 2001-2006.
+// Copyright Frank Mori Hess 2009.
+// Use, modification and
+// distribution is subject to 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)
+
+// For more information, see http://www.boost.org
+
+#include <boost/test/minimal.hpp>
+#include <boost/signals2/signal.hpp>
+#include <boost/signals2/trackable.hpp>
+#include <boost/bind.hpp>
+
+struct short_lived : public boost::signals2::trackable {
+  ~short_lived() {}
+};
+
+struct swallow {
+  typedef int result_type;
+  template<typename T> int operator()(const T*, int i) { return i; }
+};
+
+template<typename T>
+struct max_or_default {
+  typedef T result_type;
+
+  template<typename InputIterator>
+  T operator()(InputIterator first, InputIterator last) const
+  {
+    if (first == last)
+      return T();
+
+    T max = *first++;
+    for (; first != last; ++first)
+      max = (*first > max)? *first : max;
+
+    return max;
+  }
+};
+
+int test_main(int, char*[])
+{
+  typedef boost::signals2::signal1<int, int, max_or_default<int> > sig_type;
+  sig_type s1;
+
+  // Test auto-disconnection
+  BOOST_CHECK(s1(5) == 0);
+  {
+    short_lived shorty;
+    s1.connect(boost::bind<int>(swallow(), &shorty, _1));
+    BOOST_CHECK(s1(5) == 5);
+  }
+  // Test multiple arg slot constructor
+  BOOST_CHECK(s1(5) == 0);
+  {
+    short_lived shorty;
+    s1.connect(sig_type::slot_type(swallow(), &shorty, _1));
+    BOOST_CHECK(s1(5) == 5);
+  }
+
+  // Test auto-disconnection of slot before signal connection
+  {
+    short_lived* shorty = new short_lived();
+
+    sig_type::slot_type slot(boost::bind<int>(swallow(), shorty, _1));
+    delete shorty;
+
+    BOOST_CHECK(s1(5) == 0);
+  }
+
+  return 0;
+}