$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: fmhess_at_[hidden]
Date: 2007-09-25 14:09:52
Author: fmhess
Date: 2007-09-25 14:09:10 EDT (Tue, 25 Sep 2007)
New Revision: 39527
URL: http://svn.boost.org/trac/boost/changeset/39527
Log:
More documentation updates.  All the obvious problems I'm aware of should
be fixed now.
Text files modified: 
   sandbox/thread_safe_signals/libs/thread_safe_signals/doc/design.xml    |    72 ----------------                        
   sandbox/thread_safe_signals/libs/thread_safe_signals/doc/faq.xml       |    14 +-                                      
   sandbox/thread_safe_signals/libs/thread_safe_signals/doc/rationale.xml |   170 ++++++++++----------------------------- 
   sandbox/thread_safe_signals/libs/thread_safe_signals/doc/signals.xml   |     2                                         
   sandbox/thread_safe_signals/libs/thread_safe_signals/doc/tests.xml     |    13 --                                      
   sandbox/thread_safe_signals/libs/thread_safe_signals/doc/tutorial.xml  |    37 ++++++--                                
   6 files changed, 84 insertions(+), 224 deletions(-)
Modified: sandbox/thread_safe_signals/libs/thread_safe_signals/doc/design.xml
==============================================================================
--- sandbox/thread_safe_signals/libs/thread_safe_signals/doc/design.xml	(original)
+++ sandbox/thread_safe_signals/libs/thread_safe_signals/doc/design.xml	2007-09-25 14:09:10 EDT (Tue, 25 Sep 2007)
@@ -8,34 +8,6 @@
   <using-namespace name="boost::signals"/>
 
   <section>
-    <title>Type Erasure</title>
-
-    <para>"Type erasure", where static type information is eliminated
-    by the use of dynamically dispatched interfaces, is used
-    extensively within the Boost.Signals library to reduce the amount
-    of code generated by template instantiation. Each signal must
-    manage a list of slots and their associated connections, along
-    with a <code>std::map</code> to map from group identifiers to
-    their associated connections. However, instantiating this map for
-    every token type, and perhaps within each translation unit (for
-    some popular template instantiation strategies) increase compile
-    time overhead and space overhead.</para>
-
-    <para> To combat this so-called "template bloat", we use
-    Boost.Function and Boost.Any to store unknown types and
-    operations. Then, all of the code for handling the list of slots
-    and the mapping from slot identifiers to connections is factored
-    into the class <code><classname>signal_base</classname></code>
-    that deals exclusively with the <code>any</code> and
-    <code><classname>function</classname></code> objects, hiding the
-    actual implementations using the well-known pimpl idiom. The
-    actual <code><classname>signalN</classname></code> class templates
-    deal only with code that will change depending on the number of
-    arguments or which is inherently template-dependent (such as
-    connection).</para>
-  </section>
-
-  <section>
     <title><code>connection</code> class</title>
 
     <para> The <code><classname>connection</classname></code> class is
@@ -121,7 +93,7 @@
             iterator with the set of arguments given to the signal
             itself, and returns the result of that slot
             call.</para></entry>
-          </row>          
+          </row>
           <row>
             <entry><para>Input Caching Iterator Adaptor</para></entry>
             <entry><para>This iterator adaptor caches the result of
@@ -139,46 +111,4 @@
       </tgroup>
     </informaltable>
   </section>
-
-  <section>
-    <title><code>visit_each</code> function template</title>
-    
-    <para> The <code><functionname>visit_each</functionname></code>
-    function template is a mechanism for discovering objects that are
-    stored within another object. Function template
-    <code><functionname>visit_each</functionname></code> takes three
-    arguments: an object to explore, a visitor function object that is
-    invoked with each subobject, and the <code>int</code> 0. </para>
-
-    <para> The third parameter is merely a temporary solution to the
-    widespread lack of proper function template partial ordering. The
-    primary <code><functionname>visit_each</functionname></code>
-    function template specifies this third parameter type to be
-    <code>long</code>, whereas any user specializations must specify
-    their third parameter to be of type <code>int</code>. Thus, even
-    though a broken compiler cannot tell the ordering between, e.g., a
-    match against a parameter <code>T</code> and a parameter
-    <code>A<T></code>, it can determine that the conversion from
-    the integer 0 to <code>int</code> is better than the conversion to
-    <code>long</code>. The ordering determined by this conversion thus
-    achieves partial ordering of the function templates in a limited,
-    but successful, way. The following example illustrates the use of
-    this technique:</para>
-
-    <programlisting>
-template<typename> class A {};
-template<typename T> void foo(T, long);
-template<typename T> void foo(A<T>, int);
-A<T> at;
-foo(at, 0);
-</programlisting>
-
-    <para> In this example, we assume that our compiler can not tell
-    that <code>A<T></code> is a better match than
-    <code>T</code>, and therefore assume that the function templates
-    cannot be ordered based on that parameter. Then the conversion
-    from 0 to <code>int</code> is better than the conversion from 0 to
-    <code>long</code>, and the second function template is
-    chosen. </para>
-  </section>
 </section>
Modified: sandbox/thread_safe_signals/libs/thread_safe_signals/doc/faq.xml
==============================================================================
--- sandbox/thread_safe_signals/libs/thread_safe_signals/doc/faq.xml	(original)
+++ sandbox/thread_safe_signals/libs/thread_safe_signals/doc/faq.xml	2007-09-25 14:09:10 EDT (Tue, 25 Sep 2007)
@@ -24,9 +24,9 @@
       </question>
       <answer>
         <para>Yes, if the ThreadingModel template parameter of the signal is set to
-        <code>boost::signals::multi_threaded</code>, or if it is set to
-        <code>boost::signals::auto_threaded</code> and boost has detected thread support
-        in the compiler's current translation mode.  If you use <code>boost::signals::multi_threaded</code>,
+        <code>boost::signalslib::multi_threaded</code>, or if it is set to
+        <code>boost::signalslib::auto_threaded</code> and boost has detected thread support
+        in the compiler's current translation mode.  If you use <code>boost::signalslib::multi_threaded</code>,
         you will also have to link to libboost_thread.</para>
       </answer>
     </qandaentry>
@@ -39,7 +39,7 @@
         <code>signals</code> and <code>slots</code> are defined using
         preprocessor macros, causing a conflict with the <code>boost::signals</code>
         namespace.  For thread_safe_signals, <code>boost::signals</code> is actually
-        just an alias to <code>boost::signalslib</code>.  So by always using the
+        just a namespace alias to <code>boost::signalslib</code>.  So by always using the
         namespace <code>boost::signalslib</code> instead of
         <code>boost::signals</code> in your
         code, you can avoid any conflict with the Qt <code>signals</code> macro.
@@ -55,10 +55,8 @@
         Signals and Slots, the relevant part of your .pro file might
         look like this:</para>
 
-        <programlisting>
-CONFIG      += no_keywords # so Qt won't #define any non-all-caps `keywords'
-INCLUDEPATH += . /usr/local/include/boost-1_33_1/
-macx:LIBS   += /usr/local/lib/libboost_signals-1_33_1.a  # ...your exact paths may vary
+        <programlisting>CONFIG      += no_keywords # so Qt won't #define any non-all-caps `keywords'
+INCLUDEPATH += . /usr/local/include/thread_safe_signals /usr/local/include/boost-1_33_1/ # ...your exact paths may vary
 </programlisting>
 
         <para>Now you can mix Boost.Signals and Qt Signals and Slots
Modified: sandbox/thread_safe_signals/libs/thread_safe_signals/doc/rationale.xml
==============================================================================
--- sandbox/thread_safe_signals/libs/thread_safe_signals/doc/rationale.xml	(original)
+++ sandbox/thread_safe_signals/libs/thread_safe_signals/doc/rationale.xml	2007-09-25 14:09:10 EDT (Tue, 25 Sep 2007)
@@ -5,67 +5,10 @@
   <title>Design Rationale</title>
 
   <using-namespace name="boost"/>
-  <using-namespace name="boost::signals"/>
+  <using-namespace name="boost::signalslib"/>
   <using-class name="boost::signalN"/>
 
   <section>
-    <title>Choice of Slot Definitions</title> 
-
-    <para> The definition of a slot differs amongst signals and slots
-    libraries. Within Boost.Signals, a slot is defined in a very loose
-    manner: it can be any function object that is callable given
-    parameters of the types specified by the signal, and whose return
-    value is convertible to the result type expected by the
-    signal. However, alternative definitions have associated pros and
-    cons that were considered prior to the construction of
-    Boost.Signals.</para>
-
-    <itemizedlist>
-      <listitem>
-        <para><emphasis role="bold">Slots derive from a specific base
-        class</emphasis>: generally a scheme such as this will require
-        all user-defined slots to derive from some library-specified
-        <code>Slot</code> abstract class that defines a virtual
-        function calling the slot. Adaptors can be used to convert a
-        definition such as this to a definition similar to that used
-        by Boost.Signals, but the use of a large number of small
-        adaptor classes containing virtual functions has been found to
-        cause an unacceptable increase in the size of executables
-        (polymorphic class types require more code than
-        non-polymorphic types).</para>
-
-        <para> This approach does have the benefit of simplicity of
-        implementation and user interface, from an object-oriented
-        perspective.</para>
-      </listitem>
-
-      <listitem>
-        <para><emphasis role="bold">Slots constructed from a set of
-        primitives</emphasis>: in this scheme the slot can have a
-        limited set of types (often derived from a common abstract
-        base class) that are constructed from some library-defined set
-        of primitives that often include conversions from free
-        function pointers and member function pointers, and a limited
-        set of binding capabilities. Such an approach is reasonably
-        simple and cover most common cases, but it does not allow a
-        large degree of flexibility in slot construction. Libraries
-        for function object composition have become quite advanced and
-        it is out of the scope of a signals and slots library to
-        encorporate such enhancements. Thus Boost.Signals does not
-        include argument binding or function object composition
-        primitives, but instead provides a hook (via the
-        <code><functionname>visit_each</functionname></code>
-        mechanism) that allows existing binder/composition libraries
-        to provide the necessary information to Signals.</para>
-      </listitem>
-    </itemizedlist>
-
-    <para> Users not satisfied with the slot definition choice may opt
-    to replace the default slot function type with an alternative that
-    meets their specific needs.</para>
-  </section>
-
-  <section>
     <title>User-level Connection Management</title>
 
     <para> Users need to have fine control over the connection of
@@ -96,7 +39,7 @@
         existing slot we would need to be able to compare arbitrary
         function objects, which is not feasible.</para>
       </listitem>
-      
+
       <listitem>
         <para><emphasis role="bold">Pass a token to
         disconnect</emphasis>: this approach identifies slots with a
@@ -115,7 +58,7 @@
             implementation, their detection is generally
             nontrivial.</para>
           </listitem>
-          
+
           <listitem>
             <para>Tokens must be unique, otherwise two slots will have
             the same name and will be indistinguishable. In
@@ -143,6 +86,41 @@
   </section>
 
   <section>
+    <title>Automatic Connection Management</title>
+
+    <para>Automatic connection management in thread_safe_signals
+      depends on the use of <classname>boost::shared_ptr</classname> to
+      manage the lifetimes of tracked objects.  This is differs from
+      the original Boost.Signals library, which instead relied on derivation
+      from the <code><classname>boost::trackable</classname></code> class.
+      The Boost.Signals library would be
+      notified of an object's destruction by the
+      <code><classname>trackable</classname></code> destructor.
+    </para>
+    <para>Unfortunately, the <code><classname>trackable</classname></code>
+      scheme cannot be made thread safe due
+      to destructor ordering.  The destructor of an class derived from
+      <code><classname>trackable</classname></code> will always be
+      called before the destructor of the base <code><classname>trackable</classname></code>
+      class.  However, for thread-safety the connection between the signal and object
+      needs to be disconnected before the object runs its destructors.
+      Otherwise, if an object being destroyed
+      in one thread is connected to a signal concurrently
+      invoking in another thread, the signal may call into
+      a partially destroyed object.
+    </para>
+    <para>We solve this problem by requiring that tracked objects be
+      managed by <classname>shared_ptr</classname>.  Slots keep a
+      <classname>weak_ptr</classname> to every object the slot depends
+      on.  Connections to a slot are disconnected when any of its tracked
+      <classname>weak_ptr</classname>s expire.  Additionally, signals
+      create their own temporary <classname>shared_ptr</classname>s to
+      all of a slot's tracked objects prior to invoking the slot.  This
+      insures none of the tracked objects from destruct in mid-invocation.
+    </para>
+  </section>
+
+  <section>
     <title>Combiner Interface</title>
 
     <para> The Combiner interface was chosen to mimic a call to an
@@ -231,15 +209,15 @@
     return true;
   }
 
-  int get_value() const 
-  { 
+  int get_value() const
+  {
     if (!got_first)
       throw std::runtime_error("Empty!");
-    return max_value; 
+    return max_value;
   }
 
 private:
-  int  max_value; 
+  int  max_value;
   bool got_first;
 };
 </programlisting>
@@ -326,69 +304,13 @@
       </listitem>
     </itemizedlist>
   </section>
-    
-  <section>
-    <title><code>trackable</code> rationale</title>
-
-    <para> The <code><classname>trackable</classname></code>
-      class is the primary user interface to automatic connection
-      lifetime management, and its design affects users directly. Two
-      issues stick out most: the odd copying behavior of
-      <code>trackable</code>, and the limitation requiring users to
-      derive from <code>trackable</code> to create types that can
-      participate in automatic connection management.</para>
-
-    <section>
-      <title><code>trackable</code> copying behavior</title>
-
-      <para> The copying behavior of
-      <code><classname>trackable</classname></code> is essentially
-      that <code><classname>trackable</classname></code> subobjects
-      are never copied; instead, the copy operation is merely a
-      no-op. To understand this, we look at the nature of a
-      signal-slot connection and note that the connection is based on
-      the entities that are being connected; when one of the entities
-      is destroyed, the connection is destroyed. Therefore, when a
-      <code><classname>trackable</classname></code> subobject is
-      copied, we cannot copy the connections because the connections
-      don't refer to the target entity - they refer to the source
-      entity. This reason is dual to the reason signals are
-      noncopyable: the slots connected to them are connected to that
-      particular signal, not the data contained in the signal.</para>
-    </section>
-
-    <section>
-      <title>Why derivation from <code>trackable</code>?</title>
-
-      <para> For <code><classname>trackable</classname></code> to work
-      properly, there are two constraints:</para>
-
-      <itemizedlist>
-        <listitem>
-          <para><code><classname>trackable</classname></code> must
-          have storage space to keep track of all connections made to
-          this object.</para>
-        </listitem>
-
-        <listitem>
-          <para><code><classname>trackable</classname></code> must be
-          notified when the object is being destructed so that it can
-          disconnect its connections.</para>
-        </listitem>
-      </itemizedlist>
-
-      <para>Clearly, deriving from
-      <code><classname>trackable</classname></code> meets these two
-      guidelines. We have not yet found a superior solution.</para>
-    </section>
-  </section>
 
   <section>
     <title>Comparison with other Signal/Slot implementations</title>
 
     <section>
       <title>libsigc++</title>
-      
+
       <para> <ulink
       url="http://libsigc.sourceforge.net">libsigc++</ulink> is a C++
       signals & slots library that originally started as part of
@@ -399,7 +321,7 @@
       indeed Boost.Signals was strongly influenced by Karl Nelson and
       libsigc++. A cursory inspection of each library will find a
       similar syntax for the construction of signals and in the use of
-      connections and automatic connection lifetime management. There
+      connections. There
       are some major differences in design that separate these
       libraries:</para>
 
@@ -411,9 +333,7 @@
           objects (as part of the library), explicit adaptation from
           the argument and return types of the signal to the argument
           and return types of the slot (libsigc++ is, by default, more
-          strict about types than Boost.Signals). A discussion of this
-          approach with a comparison against the approach taken by
-          Boost.Signals is given in Choice of Slot Definitions.</para>
+          strict about types than Boost.Signals).</para>
         </listitem>
 
         <listitem>
Modified: sandbox/thread_safe_signals/libs/thread_safe_signals/doc/signals.xml
==============================================================================
--- sandbox/thread_safe_signals/libs/thread_safe_signals/doc/signals.xml	(original)
+++ sandbox/thread_safe_signals/libs/thread_safe_signals/doc/signals.xml	2007-09-25 14:09:10 EDT (Tue, 25 Sep 2007)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
   "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<library name="Signals" dirname="signals"
+<library name="Signals" dirname="thread_safe_signals"
          xmlns:xi="http://www.w3.org/2001/XInclude" id="signals"
          last-revision="$Date: 2007-06-12 14:01:23 -0400 (Tue, 12 Jun 2007) $">
 <libraryinfo>
Modified: sandbox/thread_safe_signals/libs/thread_safe_signals/doc/tests.xml
==============================================================================
--- sandbox/thread_safe_signals/libs/thread_safe_signals/doc/tests.xml	(original)
+++ sandbox/thread_safe_signals/libs/thread_safe_signals/doc/tests.xml	2007-09-25 14:09:10 EDT (Tue, 25 Sep 2007)
@@ -7,14 +7,13 @@
     <lib>../build/boost_signals</lib>
     <purpose>
 <para>Ensure that calling <methodname>connect</methodname> with a slot
-that has already been disconnected via deletion does not actually
+that has already expired does not actually
 connect to the slot.</para>
     </purpose>
   </run-test>
 
   <run-test filename="deletion_test.cpp">
     <lib>../../../libs/test/build/boost_test_exec_monitor</lib>
-    <lib>../build/boost_signals</lib>
     <purpose>
 <para>Test deletion of slots.</para>
     </purpose>
@@ -22,13 +21,11 @@
 
   <run-test filename="ordering_test.cpp">
     <lib>../../../libs/test/build/boost_test_exec_monitor</lib>
-    <lib>../build/boost_signals</lib>
     <purpose><para>Test slot group ordering.</para></purpose>
   </run-test>
 
   <run-test filename="signal_n_test.cpp">
     <lib>../../../libs/test/build/boost_test_exec_monitor</lib>
-    <lib>../build/boost_signals</lib>
     <purpose>
 <para>Basic test of signal/slot connections and invocation using the
 <classname>boost::signalN</classname> class templates.</para>
@@ -37,7 +34,6 @@
 
   <run-test filename="signal_test.cpp">
     <lib>../../../libs/test/build/boost_test_exec_monitor</lib>
-    <lib>../build/boost_signals</lib>
     <purpose>
 <para>Basic test of signal/slot connections and invocation using the
 <classname>boost::signal</classname> class template.</para>
@@ -50,12 +46,11 @@
     </if-fails>
   </run-test>
 
-  <run-test filename="trackable_test.cpp">
+  <run-test filename="track_test.cpp">
     <lib>../../../libs/test/build/boost_test_exec_monitor</lib>
-    <lib>../build/boost_signals</lib>
     <purpose>
-      <para>Test automatic lifetime management using
-      <classname>boost::trackable</classname> objects.</para>
+      <para>Test automatic connection management of signals
+      and slots.</para>
     </purpose>
   </run-test>
 </testsuite>
Modified: sandbox/thread_safe_signals/libs/thread_safe_signals/doc/tutorial.xml
==============================================================================
--- sandbox/thread_safe_signals/libs/thread_safe_signals/doc/tutorial.xml	(original)
+++ sandbox/thread_safe_signals/libs/thread_safe_signals/doc/tutorial.xml	2007-09-25 14:09:10 EDT (Tue, 25 Sep 2007)
@@ -474,13 +474,15 @@
   {
     // If there are no slots to call, just return the
     // default-constructed value
-    if (first == last)
-      return T();
-
-    T max_value = *first++;
+    T max_value = T();
     while (first != last) {
-      if (max_value < *first)
-        max_value = *first;
+      try {
+        if (max_value < *first)
+          max_value = *first;
+      }
+      // Iterator dereference may throw boost::expired_slot if the
+      // slot has expired due to automatic connection management.
+      catch(const boost::expired_slot &) {}
       ++first;
     }
 
@@ -554,7 +556,16 @@
   template<typename InputIterator>
   Container operator()(InputIterator first, InputIterator last) const
   {
-    return Container(first, last);
+    Container values;
+
+    while(first != last) {
+      try {
+        values.push_back(*first);
+      }
+      catch(const boost::expired_slot &) {}
+      ++first;
+    }
+    return values;
   }
 };
 </programlisting>
@@ -636,8 +647,11 @@
   result_type operator()(InputIterator first, InputIterator last) const
   {
     while (first != last) {
-      if (result_type fulfilled = *first)
-        return fulfilled;
+      try {
+        if (result_type fulfilled = *first)
+          return fulfilled;
+      }
+      catch(const boost::expired_slot &) {}
       ++first;
     }
     return 0;
@@ -1130,7 +1144,10 @@
 <section>
   <title>Linking against the Signals library</title>
   <para>The thread_safe_signals version of Boost.Signals is currently a header-only library.
-  No linking is to a compiled binary library is required.
+  However, if you use the <classname>boost::signalslib::multithreaded</classname> class as
+  the ThreadingModel template parameter for your signals, you will have to link to the
+  Boost.threads library, libboost_thread.
+  .
   </para>
 </section>