$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r49003 - in sandbox/thread_safe_signals/trunk: boost/signals2 boost/signals2/detail libs/signals2/test
From: fmhess_at_[hidden]
Date: 2008-09-29 11:05:05
Author: fmhess
Date: 2008-09-29 11:05:04 EDT (Mon, 29 Sep 2008)
New Revision: 49003
URL: http://svn.boost.org/trac/boost/changeset/49003
Log:
Tweaked interface of connection_body_base a bit.  Added free swap functions
for connection classes.  Added scoped_connection::release.  Made
scoped_connection noncopyable.
Added:
   sandbox/thread_safe_signals/trunk/libs/signals2/test/connection_test.cpp   (contents, props changed)
Text files modified: 
   sandbox/thread_safe_signals/trunk/boost/signals2/connection.hpp                |    90 ++++++++++++++++++++++++++++------------
   sandbox/thread_safe_signals/trunk/boost/signals2/detail/signal_template.hpp    |     4                                         
   sandbox/thread_safe_signals/trunk/boost/signals2/detail/slot_call_iterator.hpp |     4                                         
   sandbox/thread_safe_signals/trunk/libs/signals2/test/regression_test.cpp       |     2                                         
   sandbox/thread_safe_signals/trunk/libs/signals2/test/signal_n_test.cpp         |     2                                         
   5 files changed, 69 insertions(+), 33 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	2008-09-29 11:05:04 EDT (Mon, 29 Sep 2008)
@@ -40,13 +40,27 @@
         {
         }
         virtual ~connection_body_base() {}
-        virtual void disconnect() = 0;
+        void disconnect()
+        {
+          unique_lock<connection_body_base> lock(*this);
+          nolock_disconnect();
+        }
         void nolock_disconnect()
         {
           _connected = false;
         }
         virtual bool connected() const = 0;
-        virtual shared_ptr<void> get_blocker() = 0;
+        shared_ptr<void> get_blocker()
+        {
+          unique_lock<connection_body_base> lock(*this);
+          shared_ptr<void> blocker = _weak_blocker.lock();
+          if(blocker == 0)
+          {
+            blocker.reset(this, &null_deleter);
+            _weak_blocker = blocker;
+          }
+          return blocker;
+        }
         bool blocked() const
         {
           return !_weak_blocker.expired();
@@ -56,6 +70,10 @@
           return nolock_nograb_connected() == false || blocked();
         }
         bool nolock_nograb_connected() const {return _connected;}
+        // expose part of Lockable concept of mutex
+        virtual void lock() = 0;
+        virtual void unlock() = 0;
+
       protected:
 
         mutable bool _connected;
@@ -72,28 +90,12 @@
         {
         }
         virtual ~connection_body() {}
-        virtual void disconnect()
-        {
-          unique_lock<mutex_type> lock(mutex);
-          nolock_disconnect();
-        }
         virtual bool connected() const
         {
-          unique_lock<mutex_type> lock(mutex);
+          unique_lock<mutex_type> lock(_mutex);
           nolock_grab_tracked_objects();
           return nolock_nograb_connected();
         }
-        virtual shared_ptr<void> get_blocker()
-        {
-          unique_lock<mutex_type> lock(mutex);
-          shared_ptr<void> blocker = _weak_blocker.lock();
-          if(blocker == 0)
-          {
-            blocker.reset(this, &null_deleter);
-            _weak_blocker = blocker;
-          }
-          return blocker;
-        }
         const GroupKey& group_key() const {return _group_key;}
         void set_group_key(const GroupKey &key) {_group_key = key;}
         bool nolock_slot_expired() const
@@ -119,9 +121,18 @@
           }
           return locked_objects;
         }
+        // expose Lockable concept of mutex
+        virtual void lock()
+        {
+          _mutex.lock();
+        }
+        virtual void unlock()
+        {
+          _mutex.unlock();
+        }
         SlotType slot;
-        mutable mutex_type mutex;
       private:
+        mutable mutex_type _mutex;
         GroupKey _group_key;
       };
     }
@@ -136,7 +147,7 @@
       connection() {}
       connection(const connection &other): _weak_connection_body(other._weak_connection_body)
       {}
-      connection(boost::weak_ptr<detail::connection_body_base> connectionBody):
+      connection(const boost::weak_ptr<detail::connection_body_base> &connectionBody):
         _weak_connection_body(connectionBody)
       {}
       ~connection() {}
@@ -175,32 +186,57 @@
         using std::swap;
         swap(_weak_connection_body, other._weak_connection_body);
       }
-    private:
+    protected:
 
       boost::weak_ptr<detail::connection_body_base> _weak_connection_body;
     };
+    void swap(connection &conn1, connection &conn2)
+    {
+      conn1.swap(conn2);
+    }
 
     class scoped_connection: public connection
     {
     public:
-      scoped_connection() {}
-      scoped_connection(const connection &other): connection(other)
+      scoped_connection(): _released(false) {}
+      scoped_connection(const connection &other):
+        connection(other), _released(false)
       {}
       ~scoped_connection()
       {
-        disconnect();
+        if(_released == false)
+          disconnect();
       }
-      const scoped_connection& operator=(const connection &rhs)
+      scoped_connection& operator=(const connection &rhs)
       {
-        disconnect();
+        if(_released == false)
+          disconnect();
+        _released = false;
         connection::operator=(rhs);
         return *this;
       }
+      connection release()
+      {
+        connection conn(_weak_connection_body);
+        _released = true;
+        return conn;
+      }
       void swap(scoped_connection &other)
       {
         connection::swap(other);
+        using std::swap;
+        swap(_released, other._released);
       }
+    private:
+      scoped_connection(const scoped_connection &other);
+      scoped_connection& operator=(const scoped_connection &rhs);
+
+      bool _released;
     };
+    void swap(scoped_connection &conn1, scoped_connection &conn2)
+    {
+      conn1.swap(conn2);
+    }
   }
 }
 
Modified: sandbox/thread_safe_signals/trunk/boost/signals2/detail/signal_template.hpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/boost/signals2/detail/signal_template.hpp	(original)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/detail/signal_template.hpp	2008-09-29 11:05:04 EDT (Mon, 29 Sep 2008)
@@ -288,7 +288,7 @@
           {
             bool connected;
             {
-              unique_lock<Mutex> lock((*it)->mutex);
+              unique_lock<connection_body_base> lock(**it);
               if(grab_tracked)
                 (*it)->nolock_slot_expired();
               connected = (*it)->nolock_nograb_connected();
@@ -354,7 +354,7 @@
           for(it = local_state->connection_bodies.begin();
             it != local_state->connection_bodies.end(); ++it)
           {
-            unique_lock<Mutex> lock((*it)->mutex);
+            unique_lock<connection_body_base> lock(**it);
             if((*it)->slot.slot_function() == slot)
             {
               (*it)->nolock_disconnect();
Modified: sandbox/thread_safe_signals/trunk/boost/signals2/detail/slot_call_iterator.hpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/boost/signals2/detail/slot_call_iterator.hpp	(original)
+++ sandbox/thread_safe_signals/trunk/boost/signals2/detail/slot_call_iterator.hpp	2008-09-29 11:05:04 EDT (Mon, 29 Sep 2008)
@@ -86,7 +86,7 @@
         }
 
       private:
-        typedef unique_lock<typename ConnectionBody::mutex_type> lock_type;
+        typedef unique_lock<connection_body_base> lock_type;
 
         void lock_next_callable() const
         {
@@ -96,7 +96,7 @@
           }
           for(;iter != end; ++iter)
           {
-            lock_type lock((*iter)->mutex);
+            lock_type lock(**iter);
             tracked_ptrs = (*iter)->nolock_grab_tracked_objects();
             if((*iter)->nolock_nograb_blocked() == false)
             {
Added: sandbox/thread_safe_signals/trunk/libs/signals2/test/connection_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/test/connection_test.cpp	2008-09-29 11:05:04 EDT (Mon, 29 Sep 2008)
@@ -0,0 +1,88 @@
+// Signals2 library
+// tests for connection class
+
+// Copyright Frank Mori Hess 2008
+// 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.hpp>
+
+namespace bs2 = boost::signals2;
+
+typedef bs2::signal<void ()> sig_type;
+
+void myslot()
+{}
+
+void swap_test()
+{
+  sig_type sig;
+
+  {
+    bs2::connection conn1 = sig.connect(&myslot);
+    BOOST_CHECK(conn1.connected());
+    bs2::connection conn2;
+    BOOST_CHECK(conn2.connected() == false);
+
+    conn1.swap(conn2);
+    BOOST_CHECK(conn2.connected());
+    BOOST_CHECK(conn1.connected() == false);
+
+    swap(conn1, conn2);
+    BOOST_CHECK(conn1.connected());
+    BOOST_CHECK(conn2.connected() == false);
+  }
+
+  {
+    bs2::scoped_connection conn1 = sig.connect(&myslot);
+    BOOST_CHECK(conn1.connected());
+    bs2::scoped_connection conn2;
+    BOOST_CHECK(conn2.connected() == false);
+
+    conn1.swap(conn2);
+    BOOST_CHECK(conn2.connected());
+    BOOST_CHECK(conn1.connected() == false);
+
+    swap(conn1, conn2);
+    BOOST_CHECK(conn1.connected());
+    BOOST_CHECK(conn2.connected() == false);
+  }
+}
+
+void release_test()
+{
+  sig_type sig;
+  bs2::connection conn;
+  {
+    bs2::scoped_connection scoped(sig.connect(&myslot));
+    BOOST_CHECK(scoped.connected());
+    conn = scoped.release();
+  }
+  BOOST_CHECK(conn.connected());
+
+  bs2::connection conn2;
+  {
+    bs2::scoped_connection scoped(conn);
+    BOOST_CHECK(scoped.connected());
+    conn = scoped.release();
+    conn.disconnect();
+    BOOST_CHECK(scoped.connected() == false);
+
+    // earlier release shouldn't affect new connection
+    bs2::connection conn2 = sig.connect(&myslot);
+    scoped = conn2;
+  }
+  BOOST_CHECK(conn2.connected() == false);
+}
+
+int test_main(int, char*[])
+{
+  release_test();
+  swap_test();
+  return 0;
+}
Modified: sandbox/thread_safe_signals/trunk/libs/signals2/test/regression_test.cpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/libs/signals2/test/regression_test.cpp	(original)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/test/regression_test.cpp	2008-09-29 11:05:04 EDT (Mon, 29 Sep 2008)
@@ -67,7 +67,7 @@
   typedef boost::signals2::signal0<void, slot_counter> signal_type;
   signal_type sig;
   {
-    boost::signals2::scoped_connection conn = sig.connect(&my_slot);
+    boost::signals2::scoped_connection conn(sig.connect(&my_slot));
     BOOST_CHECK(sig() == 1);
     conn = sig.connect(&my_slot);
     BOOST_CHECK(sig() == 1);
Modified: sandbox/thread_safe_signals/trunk/libs/signals2/test/signal_n_test.cpp
==============================================================================
--- sandbox/thread_safe_signals/trunk/libs/signals2/test/signal_n_test.cpp	(original)
+++ sandbox/thread_safe_signals/trunk/libs/signals2/test/signal_n_test.cpp	2008-09-29 11:05:04 EDT (Mon, 29 Sep 2008)
@@ -179,7 +179,7 @@
   boost::signals2::signal0<void> s;
 
   {
-    boost::signals2::scoped_connection c = s.connect(boost::ref(ec));
+    boost::signals2::scoped_connection c(s.connect(boost::ref(ec)));
     BOOST_CHECK(ec.count == 0);
     s();
     BOOST_CHECK(ec.count == 1);