Boost logo

Boost-Commit :

From: fmhess_at_[hidden]
Date: 2007-06-12 11:08:33


Author: fmhess
Date: 2007-06-12 11:08:32 EDT (Tue, 12 Jun 2007)
New Revision: 6999
URL: http://svn.boost.org/trac/boost/changeset/6999

Log:
Moved more thread_safe_signals files over to
new directory structure.

Added:
   sandbox/thread_safe_signals/libs/doc/
   sandbox/thread_safe_signals/libs/doc/design.xml
      - copied unchanged from r6998, /sandbox/libs/thread_safe_signals/doc/design.xml
   sandbox/thread_safe_signals/libs/doc/faq.xml
      - copied unchanged from r6998, /sandbox/libs/thread_safe_signals/doc/faq.xml
   sandbox/thread_safe_signals/libs/doc/introduction.xml
      - copied unchanged from r6998, /sandbox/libs/thread_safe_signals/doc/introduction.xml
   sandbox/thread_safe_signals/libs/doc/rationale.xml
      - copied unchanged from r6998, /sandbox/libs/thread_safe_signals/doc/rationale.xml
   sandbox/thread_safe_signals/libs/doc/reference/
      - copied from r6998, /sandbox/libs/thread_safe_signals/doc/reference/
   sandbox/thread_safe_signals/libs/doc/signals.xml
      - copied unchanged from r6998, /sandbox/libs/thread_safe_signals/doc/signals.xml
   sandbox/thread_safe_signals/libs/doc/tests.xml
      - copied unchanged from r6998, /sandbox/libs/thread_safe_signals/doc/tests.xml
   sandbox/thread_safe_signals/libs/doc/tutorial.xml
      - copied unchanged from r6998, /sandbox/libs/thread_safe_signals/doc/tutorial.xml
   sandbox/thread_safe_signals/libs/test/
      - copied from r6997, /sandbox/libs/thread_safe_signals/test/
Removed:
   sandbox/libs/thread_safe_signals/doc/design.xml
   sandbox/libs/thread_safe_signals/doc/faq.xml
   sandbox/libs/thread_safe_signals/doc/introduction.xml
   sandbox/libs/thread_safe_signals/doc/rationale.xml
   sandbox/libs/thread_safe_signals/doc/reference/
   sandbox/libs/thread_safe_signals/doc/signals.xml
   sandbox/libs/thread_safe_signals/doc/tests.xml
   sandbox/libs/thread_safe_signals/doc/tutorial.xml
   sandbox/libs/thread_safe_signals/test/

Deleted: sandbox/libs/thread_safe_signals/doc/design.xml
==============================================================================
--- sandbox/libs/thread_safe_signals/doc/design.xml 2007-06-12 11:08:32 EDT (Tue, 12 Jun 2007)
+++ (empty file)
@@ -1,184 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
- "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<section last-revision="$Date$">
- <title>Design Overview</title>
-
- <using-namespace name="boost"/>
- <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
- central to the behavior of the Boost.Signals library. It is the
- only entity within the Boost.Signals system that has knowledge of
- all objects that are associated by a given connection. To be
- specific, the <code><classname>connection</classname></code> class
- itself is merely a thin wrapper over a
- <code><classname>shared_ptr</classname></code> to a
- <code>basic_connection</code> object.</para>
-
- <para> <code><classname>connection</classname></code> objects are
- stored by all participants in the Signals system: each
- <code><classname>trackable</classname></code> object contains a
- list of <code><classname>connection</classname></code> objects
- describing all connections it is a part of; similarly, all signals
- contain a set of pairs that define a slot. The pairs consist of a
- slot function object (generally a Boost.Function object) and a
- <code><classname>connection</classname></code> object (that will
- disconnect on destruction). Finally, the mapping from slot groups
- to slots is based on the key value in a
- <code><classname>std::multimap</classname></code> (the stored data
- in the <code><classname>std::multimap</classname></code> is the
- slot pair).</para>
- </section>
-
- <section>
- <title>Slot Call Iterator</title>
-
- <para> The slot call iterator is conceptually a stack of iterator
- adaptors that modify the behavior of the underlying iterator
- through the list of slots. The following table describes the type
- and behavior of each iterator adaptor required. Note that this is
- only a conceptual model: the implementation collapses all these
- layers into a single iterator adaptor because several popular
- compilers failed to compile the implementation of the conceptual
- model.</para>
-
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Iterator Adaptor</entry>
- <entry>Purpose</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><para>Slot List Iterator</para></entry>
- <entry><para>An iterator through the list of slots
- connected to a signal. The <code>value_type</code> of this
- iterator will be
- <code><classname>std::pair</classname>&lt;any,
- connection&gt;</code>, where the
- <code><classname>any</classname></code> contains an
- instance of the slot function type.</para></entry>
- </row>
- <row>
- <entry><para>Filter Iterator Adaptor</para></entry>
- <entry><para>This filtering iterator adaptor filters out
- slots that have been disconnected, so we never see a
- disconnected slot in later stages.</para></entry>
- </row>
- <row>
- <entry><para>Projection Iterator Adaptor</para></entry>
- <entry><para>The projection iterator adaptor returns a
- reference to the first member of the pair that constitutes
- a connected slot (e.g., just the
- <code><classname>boost::any</classname></code> object that
- holds the slot function).</para></entry>
- </row>
- <row>
- <entry><para>Transform Iterator Adaptor</para></entry>
- <entry><para>This transform iterator adaptor performs an
- <code><functionname>any_cast</functionname></code> to
- extract a reference to the slot function with the
- appropriate slot function type.</para></entry>
- </row>
- <row>
- <entry><para>Transform Iterator Adaptor</para></entry>
- <entry><para>This transform iterator adaptor calls the
- function object returned by dereferencing the underlying
- iterator with the set of arguments given to the signal
- itself, and returns the result of that slot
- call.</para></entry>
- </row>
- <row>
- <entry><para>Input Caching Iterator Adaptor</para></entry>
- <entry><para>This iterator adaptor caches the result of
- dereferencing the underlying iterator. Therefore,
- dereferencing this iterator multiple times will only
- result in the underlying iterator being dereferenced once;
- thus, a slot can only be called once but its result can be
- used multiple times.</para></entry>
- </row>
- <row>
- <entry><para>Slot Call Iterator</para></entry>
- <entry><para>Iterates over calls to each slot.</para></entry>
- </row>
- </tbody>
- </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&lt;T&gt;</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&lt;typename&gt; class A {};
-template&lt;typename T&gt; void foo(T, long);
-template&lt;typename T&gt; void foo(A&lt;T&gt;, int);
-A&lt;T&gt; at;
-foo(at, 0);
-</programlisting>
-
- <para> In this example, we assume that our compiler can not tell
- that <code>A&lt;T&gt;</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>

Deleted: sandbox/libs/thread_safe_signals/doc/faq.xml
==============================================================================
--- sandbox/libs/thread_safe_signals/doc/faq.xml 2007-06-12 11:08:32 EDT (Tue, 12 Jun 2007)
+++ (empty file)
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
- "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<section last-revision="$Date$">
- <title>Frequently Asked Questions</title>
-
- <qandaset>
- <qandaentry>
- <question>
- <para>Don't noncopyable signal semantics mean that a class
- with a signal member will be noncopyable as well?</para>
- </question>
- <answer>
- <para>No. The compiler will not be able to generate a copy
- constructor or copy assignment operator for your class if it
- has a signal as a member, but you are free to write your own
- copy constructor and/or copy assignment operator. Just don't
- try to copy the signal.</para>
- </answer>
- </qandaentry>
- <qandaentry>
- <question>
- <para>Is Boost.Signals thread-safe?</para>
- </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>,
- you will also have to link to libboost_thread.</para>
- </answer>
- </qandaentry>
- <qandaentry>
- <question>
- <para>How do I get Boost.Signals to work with Qt?</para>
- </question>
- <answer>
- <para>When building with Qt, the Moc keywords
- <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
- 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.
- </para>
-
- <para>Alternatively, for <emphasis>Qt 4.1 and later</emphasis>
- the <code>signals</code> and <code>slots</code> macros
- can be turned off in Qt on a per-project or per-file basis
- with the <code>no_keywords</code> option. This works with
- out-of-the-box builds of Boost and Qt. You do not need to
- re-configure, re-build, or duplicate existing libraries. For a
- project where you want to use both Boost.Signals and Qt
- 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>
-
- <para>Now you can mix Boost.Signals and Qt Signals and Slots
- in the same files, and even within the same class or function.
- You will have to use the upper-case versions of Qt macros in
- your own code. See the article <ulink
- url="http://scottcollins.net/articles/a-deeper-look-at-signals-and-slots.html">A
- Deeper Look at Signals and Slots</ulink> [off-site] for more
- complete examples and a survey of the strengths of the two
- systems.</para>
-
- </answer>
- </qandaentry>
- </qandaset>
-</section>

Deleted: sandbox/libs/thread_safe_signals/doc/introduction.xml
==============================================================================
--- sandbox/libs/thread_safe_signals/doc/introduction.xml 2007-06-12 11:08:32 EDT (Tue, 12 Jun 2007)
+++ (empty file)
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
- "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<section last-revision="$Date$">
- <title>Introduction</title>
-
-<para>The Boost.Signals library is an implementation of a managed
-signals and slots system. Signals represent callbacks with multiple
-targets, and are also called publishers or events in similar
-systems. Signals are connected to some set of slots, which are
-callback receivers (also called event targets or subscribers), which
-are called when the signal is "emitted."</para>
-
-<para>Signals and slots are managed, in that signals and slots (or,
-more properly, objects that occur as part of the slots) can track
-connections and are capable of automatically disconnecting signal/slot
-connections when either is destroyed. This enables the user to make
-signal/slot connections without expending a great effort to manage the
-lifetimes of those connections with regard to the lifetimes of all
-objects involved.</para>
-
-<para>When signals are connected to multiple slots, there is a
-question regarding the relationship between the return values of the
-slots and the return value of the signals. Boost.Signals allows the
-user to specify the manner in which multiple return values are
-combined.</para>
-
-<para>This documentation describes a thread-safe variant of the
-official Boost.Signals library. There have been some changes to
-the interface to support thread-safety, mostly with respect to
-automatic connection management. This implementation was written by
-Frank Mori Hess. Acknowledgements are also due to Timmo Stange, Peter
-Dimov, and Gottlob Frege for ideas and feedback, and to Douglas Gregor
-for the original version of Boost.Signals this effort was based on.
-</para>
-
-</section>
\ No newline at end of file

Deleted: sandbox/libs/thread_safe_signals/doc/rationale.xml
==============================================================================
--- sandbox/libs/thread_safe_signals/doc/rationale.xml 2007-06-12 11:08:32 EDT (Tue, 12 Jun 2007)
+++ (empty file)
@@ -1,454 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
- "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<section last-revision="$Date$">
- <title>Design Rationale</title>
-
- <using-namespace name="boost"/>
- <using-namespace name="boost::signals"/>
- <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
- signals to slots and their eventual disconnection. The approach
- taken by Boost.Signals is to return a
- <code><classname>connection</classname></code> object that enables
- connected/disconnected query, manual disconnection, and an
- automatic disconnection on destruction mode. Some other possible
- interfaces include:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">Pass slot to
- disconnect</emphasis>: in this interface model, the
- disconnection of a slot connected with
- <code>sig.<methodname>connect</methodname>(slot)</code> is
- performed via
- <code>sig.<methodname>disconnect</methodname>(slot)</code>. Internally,
- a linear search using slot comparison is performed and the
- slot, if found, is removed from the list. Unfortunately,
- querying connectedness will generally also end up as
- linear-time operations. This model also fails for
- implementation reasons when slots become more complex than
- simple function pointers, member function pointers and a
- limited set of compositions and argument binders: to match the
- slot given in the call to
- <code><methodname>disconnect</methodname></code> with an
- 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
- token that is easily comparable (e.g., a string), enabling
- slots to be arbitrary function objects. While this approach is
- essentially equivalent to the approach taken by Boost.Signals,
- it is possibly more error-prone for several reasons:</para>
-
- <itemizedlist>
- <listitem>
- <para>Connections and disconnections must be paired, so
- the problem becomes similar to the problems incurred when
- pairing <code>new</code> and <code>delete</code> for
- dynamic memory allocation. While errors of this sort would
- not be catastrophic for a signals and slots
- 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
- environments where many connections will be made
- dynamically, name generation becomes an additional task
- for the user. Uniqueness of tokens also results in an
- additional failure mode when attempting to connect a slot
- using a token that has already been used.</para>
- </listitem>
-
- <listitem>
- <para>More parameterization would be required, because the
- token type must be user-defined. Additional
- parameterization steepens the learning curver and
- overcomplicates a simple interface.</para>
- </listitem>
- </itemizedlist>
-
- <para> This type of interface is supported in Boost.Signals
- via the slot grouping mechanism. It augments the
- <code><classname>connection</classname></code> object-based
- connection management scheme.</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>Combiner Interface</title>
-
- <para> The Combiner interface was chosen to mimic a call to an
- algorithm in the C++ standard library. It is felt that by viewing
- slot call results as merely a sequence of values accessed by input
- iterators, the combiner interface would be most natural to a
- proficient C++ programmer. Competing interface design generally
- required the combiners to be constructed to conform to an
- interface that would be customized for (and limited to) the
- Signals library. While these interfaces are generally enable more
- straighforward implementation of the signals &amp; slots
- libraries, the combiners are unfortunately not reusable (either in
- other signals &amp; slots libraries or within other generic
- algorithms), and the learning curve is steepened slightly to learn
- the specific combiner interface.</para>
-
- <para> The Signals formulation of combiners is based on the
- combiner using the "pull" mode of communication, instead of the
- more complex "push" mechanism. With a "pull" mechanism, the
- combiner's state can be kept on the stack and in the program
- counter, because whenever new data is required (i.e., calling the
- next slot to retrieve its return value), there is a simple
- interface to retrieve that data immediately and without returning
- from the combiner's code. Contrast this with the "push" mechanism,
- where the combiner must keep all state in class members because
- the combiner's routines will be invoked for each signal
- called. Compare, for example, a combiner that returns the maximum
- element from calling the slots. If the maximum element ever
- exceeds 100, no more slots are to be called.</para>
-
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry><para>Pull</para></entry>
- <entry><para>Push</para></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-struct pull_max {
- typedef int result_type;
-
- template&lt;typename InputIterator&gt;
- result_type operator()(InputIterator first,
- InputIterator last)
- {
- if (first == last)
- throw std::runtime_error("Empty!");
-
- int max_value = *first++;
- while(first != last &amp;&amp; *first &lt;= 100) {
- if (*first &gt; max_value)
- max_value = *first;
- ++first;
- }
-
- return max_value;
- }
-};
-</programlisting>
-</entry>
- <entry>
-<programlisting>
-struct push_max {
- typedef int result_type;
-
- push_max() : max_value(), got_first(false) {}
-
- // returns false when we want to stop
- bool operator()(int result) {
- if (result &gt; 100)
- return false;
-
- if (!got_first) {
- got_first = true;
- max_value = result;
- return true;
- }
-
- if (result &gt; max_value)
- max_value = result;
-
- return true;
- }
-
- int get_value() const
- {
- if (!got_first)
- throw std::runtime_error("Empty!");
- return max_value;
- }
-
-private:
- int max_value;
- bool got_first;
-};
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>There are several points to note in these examples. The
- "pull" version is a reusable function object that is based on an
- input iterator sequence with an integer <code>value_type</code>,
- and is very straightforward in design. The "push" model, on the
- other hand, relies on an interface specific to the caller and is
- not generally reusable. It also requires extra state values to
- determine, for instance, if any elements have been
- received. Though code quality and ease-of-use is generally
- subjective, the "pull" model is clearly shorter and more reusable
- and will often be construed as easier to write and understand,
- even outside the context of a signals &amp; slots library.</para>
-
- <para> The cost of the "pull" combiner interface is paid in the
- implementation of the Signals library itself. To correctly handle
- slot disconnections during calls (e.g., when the dereference
- operator is invoked), one must construct the iterator to skip over
- disconnected slots. Additionally, the iterator must carry with it
- the set of arguments to pass to each slot (although a reference to
- a structure containing those arguments suffices), and must cache
- the result of calling the slot so that multiple dereferences don't
- result in multiple calls. This apparently requires a large degree
- of overhead, though if one considers the entire process of
- invoking slots one sees that the overhead is nearly equivalent to
- that in the "push" model, but we have inverted the control
- structures to make iteration and dereference complex (instead of
- making combiner state-finding complex).</para>
- </section>
-
- <section>
- <title>Connection Interfaces: += operator</title>
-
- <para> Boost.Signals supports a connection syntax with the form
- <code>sig.<methodname>connect</methodname>(slot)</code>, but a
- more terse syntax <code>sig += slot</code> has been suggested (and
- has been used by other signals &amp; slots implementations). There
- are several reasons as to why this syntax has been
- rejected:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">It's unnecessary</emphasis>: the
- connection syntax supplied by Boost.Signals is no less
- powerful that that supplied by the <code>+=</code>
- operator. The savings in typing (<code>connect()</code>
- vs. <code>+=</code>) is essentially negligible. Furthermore,
- one could argue that calling <code>connect()</code> is more
- readable than an overload of <code>+=</code>.</para>
- </listitem>
- <listitem>
- <para><emphasis role="bold">Ambiguous return type</emphasis>:
- there is an ambiguity concerning the return value of the
- <code>+=</code> operation: should it be a reference to the
- signal itself, to enable <code>sig += slot1 += slot2</code>,
- or should it return a
- <code><classname>connection</classname></code> for the
- newly-created signal/slot connection?</para>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">Gateway to operators -=,
- +</emphasis>: when one has added a connection operator
- <code>+=</code>, it seems natural to have a disconnection
- operator <code>-=</code>. However, this presents problems when
- the library allows arbitrary function objects to implicitly
- become slots, because slots are no longer comparable. <!--
- (see the discussion on this topic in User-level Connection
- Management). --></para>
-
- <para> The second obvious addition when one has
- <code>operator+=</code> would be to add a <code>+</code>
- operator that supports addition of multiple slots, followed by
- assignment to a signal. However, this would require
- implementing <code>+</code> such that it can accept any two
- function objects, which is technically infeasible.</para>
- </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 &amp; slots library that originally started as part of
- an initiative to wrap the C interfaces to <ulink
- url="http://www.gtk.org">GTK</ulink> libraries in C++, and has
- grown to be a separate library maintained by Karl Nelson. There
- are many similarities between libsigc++ and Boost.Signals, and
- 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
- are some major differences in design that separate these
- libraries:</para>
-
- <itemizedlist>
- <listitem>
- <para><emphasis role="bold">Slot definitions</emphasis>:
- slots in libsigc++ are created using a set of primitives
- defined by the library. These primitives allow binding of
- 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>
- </listitem>
-
- <listitem>
- <para><emphasis role="bold">Combiner/Marshaller
- interface</emphasis>: the equivalent to Boost.Signals
- combiners in libsigc++ are the marshallers. Marshallers are
- similar to the "push" interface described in Combiner
- Interface, and a proper treatment of the topic is given
- there.</para>
- </listitem>
- </itemizedlist>
- </section>
-
- <section>
- <title>.NET delegates</title>
-
- <para> <ulink url="http://www.microsoft.com">Microsoft</ulink>
- has introduced the .NET Framework and an associated set of
- languages and language extensions, one of which is the
- delegate. Delegates are similar to signals and slots, but they
- are more limited than most C++ signals and slots implementations
- in that they:</para>
-
- <itemizedlist>
- <listitem>
- <para>Require exact type matches between a delegate and what
- it is calling.</para>
- </listitem>
-
- <listitem><para>Only return the result of the last target called, with no option for customization.</para></listitem>
- <listitem>
- <para>Must call a method with <code>this</code> already
- bound.</para>
- </listitem>
- </itemizedlist>
- </section>
- </section>
-</section>

Deleted: sandbox/libs/thread_safe_signals/doc/signals.xml
==============================================================================
--- sandbox/libs/thread_safe_signals/doc/signals.xml 2007-06-12 11:08:32 EDT (Tue, 12 Jun 2007)
+++ (empty file)
@@ -1,50 +0,0 @@
-<?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"
- xmlns:xi="http://www.w3.org/2001/XInclude" id="signals"
- last-revision="$Date$">
-<libraryinfo>
- <author>
- <firstname>Douglas</firstname>
- <surname>Gregor</surname>
- <!-- <email>gregod_at_[hidden]</email> -->
- </author>
- <author>
- <firstname>Frank</firstname>
- <surname>Hess</surname>
- <!-- <email>fmhess_at_[hidden]</email> -->
- </author>
-
- <copyright>
- <year>2001</year>
- <year>2002</year>
- <year>2003</year>
- <year>2004</year>
- <holder>Douglas Gregor</holder>
- </copyright>
- <copyright>
- <year>2007</year>
- <holder>Frank Mori Hess</holder>
- </copyright>
-
- <legalnotice>
- <para>Use, modification and distribution is subject to the Boost
- Software License, Version 1.0. (See accompanying file
- <filename>LICENSE_1_0.txt</filename> or copy at <ulink
- url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)</para>
- </legalnotice>
-
- <librarypurpose>Managed signals &amp; slots callback implementation</librarypurpose>
- <librarycategory name="category:higher-order"/>
-</libraryinfo>
-
-<title>Boost.Signals (thread_safe_signals version)</title>
- <xi:include href="introduction.xml"/>
- <xi:include href="tutorial.xml"/>
- <xi:include href="reference/reference.xml"/>
- <xi:include href="faq.xml"/>
- <xi:include href="design.xml"/>
- <xi:include href="rationale.xml"/>
- <xi:include href="tests.xml"/>
-</library>

Deleted: sandbox/libs/thread_safe_signals/doc/tests.xml
==============================================================================
--- sandbox/libs/thread_safe_signals/doc/tests.xml 2007-06-12 11:08:32 EDT (Tue, 12 Jun 2007)
+++ (empty file)
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE testsuite PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
- "
http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<testsuite last-revision="$Date$">
- <run-test filename="dead_slot_test.cpp">
- <lib>../../../libs/test/build/boost_test_exec_monitor</lib>
- <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
-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>
- </run-test>
-
- <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>
- </purpose>
- </run-test>
-
- <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>
- </purpose>
- <if-fails>
-<para>The <classname>boost::signal</classname> class template may not
-be usable on your compiler. However, the
-<classname>boost::signalN</classname> class templates may still be
-usable.</para>
- </if-fails>
- </run-test>
-
- <run-test filename="trackable_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>
- </purpose>
- </run-test>
-</testsuite>

Deleted: sandbox/libs/thread_safe_signals/doc/tutorial.xml
==============================================================================
--- sandbox/libs/thread_safe_signals/doc/tutorial.xml 2007-06-12 11:08:32 EDT (Tue, 12 Jun 2007)
+++ (empty file)
@@ -1,1137 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
- "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
-<section last-revision="$Date$" id="signals.tutorial">
- <title>Tutorial</title>
-
- <using-namespace name="boost"/>
- <using-namespace name="boost::signals"/>
- <using-class name="boost::signalN"/>
- <using-class name="boost::slotN"/>
-
- <section>
- <title>How to Read this Tutorial</title>
-<para>This tutorial is not meant to be read linearly. Its top-level
-structure roughly separates different concepts in the library
-(e.g., handling calling multiple slots, passing values to and from
-slots) and in each of these concepts the basic ideas are presented
-first and then more complex uses of the library are described
-later. Each of the sections is marked <emphasis>Beginner</emphasis>,
-<emphasis>Intermediate</emphasis>, or <emphasis>Advanced</emphasis> to help guide the
-reader. The <emphasis>Beginner</emphasis> sections include information that all
-library users should know; one can make good use of the Signals
-library after having read only the <emphasis>Beginner</emphasis> sections. The
-<emphasis>Intermediate</emphasis> sections build on the <emphasis>Beginner</emphasis>
-sections with slightly more complex uses of the library. Finally,
-the <emphasis>Advanced</emphasis> sections detail very advanced uses of the
-Signals library, that often require a solid working knowledge of
-the <emphasis>Beginner</emphasis> and <emphasis>Intermediate</emphasis> topics; most users
-will not need to read the <emphasis>Advanced</emphasis> sections.</para>
-</section>
-
-<section><title>Compatibility Note</title>
-
-<para>Boost.Signals has two syntactical forms: the preferred form and
-the compatibility form. The preferred form fits more closely with the
-C++ language and reduces the number of separate template parameters
-that need to be considered, often improving readability; however, the
-preferred form is not supported on all platforms due to compiler
-bugs. The compatible form will work on all compilers supported by
-Boost.Signals. Consult the table below to determine which syntactic
-form to use for your compiler. Users of Boost.Function, please note
-that the preferred syntactic form in Signals is equivalent to that of
-Function's preferred syntactic form.</para>
-
-<para>If your compiler does not appear in this list, please try the
-preferred syntax and report your results to the Boost list so that
-we can keep this table up-to-date.</para>
-
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <itemizedlist>
- <listitem><para>GNU C++ 2.95.x, 3.0.x, 3.1.x, 4.1.x</para></listitem>
- <listitem><para>Comeau C++ 4.2.45.2</para></listitem>
- <listitem><para>SGI MIPSpro 7.3.0</para></listitem>
- <listitem><para>Intel C++ 5.0, 6.0</para></listitem>
- <listitem><para>Compaq's cxx 6.2</para></listitem>
- <listitem><para>Microsoft Visual C++ 7.1</para></listitem>
- </itemizedlist>
- </entry>
- <entry>
- <itemizedlist>
- <listitem><para><emphasis>Any compiler supporting the preferred syntax</emphasis></para></listitem>
- <listitem><para>Microsoft Visual C++ 6.0, 7.0</para></listitem>
- <listitem><para>Borland C++ 5.5.1</para></listitem>
- <listitem><para>Sun WorkShop 6 update 2 C++ 5.3</para></listitem>
- <listitem><para>Metrowerks CodeWarrior 8.1</para></listitem>
- </itemizedlist>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-</section>
-
-<section><title>Hello, World! (Beginner)</title>
-<para>The following example writes "Hello, World!" using signals and
-slots. First, we create a signal <code>sig</code>, a signal that
-takes no arguments and has a void return value. Next, we connect
-the <code>hello</code> function object to the signal using the
-<code>connect</code> method. Finally, use the signal
-<code>sig</code> like a function to call the slots, which in turns
-invokes <code>HelloWorld::operator()</code> to print "Hello,
-World!".</para>
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-struct HelloWorld
-{
- void operator()() const
- {
- std::cout &lt;&lt; "Hello, World!" &lt;&lt; std::endl;
- }
-};
-
-// ...
-
-// Signal with no arguments and a void return value
-<classname>boost::signal</classname>&lt;void ()&gt; sig;
-
-// Connect a HelloWorld slot
-HelloWorld hello;
-sig.<methodname>connect</methodname>(hello);
-
-// Call all of the slots
-sig();
-</programlisting>
-</entry>
-<entry>
-<programlisting>
-struct HelloWorld
-{
- void operator()() const
- {
- std::cout &lt;&lt; "Hello, World!" &lt;&lt; std::endl;
- }
-};
-
-// ...
-
-// Signal with no arguments and a void return value
-<classname alt="boost::signalN">boost::signal0</classname>&lt;void&gt; sig;
-
-// Connect a HelloWorld slot
-HelloWorld hello;
-sig.<methodname>connect</methodname>(hello);
-
-// Call all of the slots
-sig();
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-</section>
-
-<section><title>Calling multiple slots</title>
-<section><title>Connecting multiple slots (Beginner)</title>
-<para>Calling a single slot from a signal isn't very interesting, so
-we can make the Hello, World program more interesting by splitting
-the work of printing "Hello, World!" into two completely separate
-slots. The first slot will print "Hello" and may look like
-this:</para>
-<programlisting>
-struct Hello
-{
- void operator()() const
- {
- std::cout &lt;&lt; "Hello";
- }
-};
-</programlisting>
-<para>The second slot will print ", World!" and a newline, to complete
-the program. The second slot may look like this:</para>
-<programlisting>
-struct World
-{
- void operator()() const
- {
- std::cout &lt;&lt; ", World!" &lt;&lt; std::endl;
- }
-};
-</programlisting>
-<para>Like in our previous example, we can create a signal
-<code>sig</code> that takes no arguments and has a
-<code>void</code> return value. This time, we connect both a
-<code>hello</code> and a <code>world</code> slot to the same
-signal, and when we call the signal both slots will be called.</para>
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-<classname>boost::signal</classname>&lt;void ()&gt; sig;
-
-sig.<methodname>connect</methodname>(Hello());
-sig.<methodname>connect</methodname>(World());
-
-sig();
-</programlisting>
-</entry>
-<entry>
-<programlisting>
-<classname alt="boost::signalN">boost::signal0</classname>&lt;void&gt; sig;
-
-sig.<methodname>connect</methodname>(Hello());
-sig.<methodname>connect</methodname>(World());
-
-sig();
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-<para>By default, slots are called in first-in first-out (FIFO) order,
-so the output of this program will be as expected:</para>
-<programlisting>
-Hello, World!
-</programlisting>
-</section>
-
-<section><title>Ordering slot call groups (Intermediate)</title>
-<para>Slots are free to have side effects, and that can mean that some
-slots will have to be called before others even if they are not connected in that order. The Boost.Signals
-library allows slots to be placed into groups that are ordered in
-some way. For our Hello, World program, we want "Hello" to be
-printed before ", World!", so we put "Hello" into a group that must
-be executed before the group that ", World!" is in. To do this, we
-can supply an extra parameter at the beginning of the
-<code>connect</code> call that specifies the group. Group values
-are, by default, <code>int</code>s, and are ordered by the integer
-&lt; relation. Here's how we construct Hello, World:</para>
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-<classname>boost::signal</classname>&lt;void ()&gt; sig;
-sig.<methodname>connect</methodname>(1, World());
-sig.<methodname>connect</methodname>(0, Hello());
-sig();
-</programlisting>
-</entry>
- <entry>
-<programlisting>
-<classname alt="boost::signalN">boost::signal0</classname>&lt;void&gt; sig;
-sig.<methodname>connect</methodname>(1, World());
-sig.<methodname>connect</methodname>(0, Hello());
-sig();
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
-<para>This program will correctly print "Hello, World!", because the
-<code>Hello</code> object is in group 0, which precedes group 1 where
-the <code>World</code> object resides. The group
-parameter is, in fact, optional. We omitted it in the first Hello,
-World example because it was unnecessary when all of the slots are
-independent. So what happens if we mix calls to connect that use the
-group parameter and those that don't? The "unnamed" slots (i.e., those
-that have been connected without specifying a group name) can be
-placed at the front or back of the slot list (by passing
-<code>boost::signals::at_front</code> or <code>boost::signals::at_back</code>
-as the last parameter to <code><methodname
-alt="boost::signalN::connect">connect</methodname></code>, respectively), and defaults to the end of the list. When
-a group is specified, the final parameter describes where the slot
-will be placed within the group ordering. If we add a new slot
-to our example like this:</para>
-<programlisting>
-struct GoodMorning
-{
- void operator()() const
- {
- std::cout &lt;&lt; "... and good morning!" &lt;&lt; std::endl;
- }
-};
-
-sig.<methodname>connect</methodname>(GoodMorning());
-</programlisting>
-<para>... we will get the result we wanted:</para>
-<programlisting>
-Hello, World!
-... and good morning!
-</programlisting>
-</section>
-</section>
-
-<section><title>Passing values to and from slots</title>
-<section><title>Slot Arguments (Beginner)</title>
-<para>Signals can propagate arguments to each of the slots they call.
-For instance, a signal that propagates mouse motion events might
-want to pass along the new mouse coordinates and whether the mouse
-buttons are pressed.</para>
-<para>As an example, we'll create a signal that passes two
-<code>float</code> arguments to its slots. Then we'll create a few
-slots that print the results of various arithmetic operations on
-these values.</para>
-<programlisting>
-void print_sum(float x, float y)
-{
- std::cout &lt;&lt; "The sum is " &lt;&lt; x+y &lt;&lt; std::endl;
-}
-
-void print_product(float x, float y)
-{
- std::cout &lt;&lt; "The product is " &lt;&lt; x*y &lt;&lt; std::endl;
-}
-
-void print_difference(float x, float y)
-{
- std::cout &lt;&lt; "The difference is " &lt;&lt; x-y &lt;&lt; std::endl;
-}
-
-void print_quotient(float x, float y)
-{
- std::cout &lt;&lt; "The quotient is " &lt;&lt; x/y &lt;&lt; std::endl;
-}
-</programlisting>
-
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-<classname>boost::signal</classname>&lt;void (float, float)&gt; sig;
-
-sig.<methodname>connect</methodname>(&amp;print_sum);
-sig.<methodname>connect</methodname>(&amp;print_product);
-sig.<methodname>connect</methodname>(&amp;print_difference);
-sig.<methodname>connect</methodname>(&amp;print_quotient);
-
-sig(5, 3);
-</programlisting>
-</entry>
-<entry>
-<programlisting>
-<classname alt="boost::signalN">boost::signal2</classname>&lt;void, float, float&gt; sig;
-
-sig.<methodname>connect</methodname>(&amp;print_sum);
-sig.<methodname>connect</methodname>(&amp;print_product);
-sig.<methodname>connect</methodname>(&amp;print_difference);
-sig.<methodname>connect</methodname>(&amp;print_quotient);
-
-sig(5, 3);
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
-<para>This program will print out the following:</para>
-<programlisting>
-The sum is 8
-The product is 15
-The difference is 2
-The quotient is 1.66667
-</programlisting>
-<para>So any values that are given to <code>sig</code> when it is
-called like a function are passed to each of the slots. We have to
-declare the types of these values up front when we create the
-signal. The type <code><classname>boost::signal</classname>&lt;void (float,
-float)&gt;</code> means that the signal has a <code>void</code>
-return value and takes two <code>float</code> values. Any slot
-connected to <code>sig</code> must therefore be able to take two
-<code>float</code> values.</para>
-</section>
-
-<section><title>Signal Return Values (Advanced)</title>
-<para>Just as slots can receive arguments, they can also return
-values. These values can then be returned back to the caller of the
-signal through a <firstterm>combiner</firstterm>. The combiner is a mechanism
-that can take the results of calling slots (there many be no
-results or a hundred; we don't know until the program runs) and
-coalesces them into a single result to be returned to the caller.
-The single result is often a simple function of the results of the
-slot calls: the result of the last slot call, the maximum value
-returned by any slot, or a container of all of the results are some
-possibilities.</para>
-<para>We can modify our previous arithmetic operations example
-slightly so that the slots all return the results of computing the
-product, quotient, sum, or difference. Then the signal itself can
-return a value based on these results to be printed:</para>
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-float product(float x, float y) { return x*y; }
-float quotient(float x, float y) { return x/y; }
-float sum(float x, float y) { return x+y; }
-float difference(float x, float y) { return x-y; }
-
-<classname>boost::signal</classname>&lt;float (float x, float y)&gt; sig;
-
-sig.<methodname>connect</methodname>(&amp;product);
-sig.<methodname>connect</methodname>(&amp;quotient);
-sig.<methodname>connect</methodname>(&amp;sum);
-sig.<methodname>connect</methodname>(&amp;difference);
-
-std::cout &lt;&lt; sig(5, 3) &lt;&lt; std::endl;
-</programlisting>
-</entry>
-<entry>
-<programlisting>
-float product(float x, float y) { return x*y; }
-float quotient(float x, float y) { return x/y; }
-float sum(float x, float y) { return x+y; }
-float difference(float x, float y) { return x-y; }
-
-<classname alt="boost::signalN">boost::signal2</classname>&lt;float, float, float&gt; sig;
-
-sig.<methodname>connect</methodname>(&amp;product);
-sig.<methodname>connect</methodname>(&amp;quotient);
-sig.<methodname>connect</methodname>(&amp;sum);
-sig.<methodname>connect</methodname>(&amp;difference);
-
-std::cout &lt;&lt; sig(5, 3) &lt;&lt; std::endl;
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
-<para>This example program will output <code>2</code>. This is because the
-default behavior of a signal that has a return type
-(<code>float</code>, the first template argument given to the
-<code><classname>boost::signal</classname></code> class template) is to call all slots and
-then return the result returned by the last slot called. This
-behavior is admittedly silly for this example, because slots have
-no side effects and the result is the last slot connect.</para>
-<para>A more interesting signal result would be the maximum of the
-values returned by any slot. To do this, we create a custom
-combiner that looks like this:</para>
-<programlisting>
-template&lt;typename T&gt;
-struct maximum
-{
- typedef T result_type;
-
- template&lt;typename InputIterator&gt;
- T operator()(InputIterator first, InputIterator last) const
- {
- // If there are no slots to call, just return the
- // default-constructed value
- if (first == last)
- return T();
-
- T max_value = *first++;
- while (first != last) {
- if (max_value &lt; *first)
- max_value = *first;
- ++first;
- }
-
- return max_value;
- }
-};
-</programlisting>
-<para>The <code>maximum</code> class template acts as a function
-object. Its result type is given by its template parameter, and
-this is the type it expects to be computing the maximum based on
-(e.g., <code>maximum&lt;float&gt;</code> would find the maximum
-<code>float</code> in a sequence of <code>float</code>s). When a
-<code>maximum</code> object is invoked, it is given an input
-iterator sequence <code>[first, last)</code> that includes the
-results of calling all of the slots. <code>maximum</code> uses this
-input iterator sequence to calculate the maximum element, and
-returns that maximum value.</para>
-<para>We actually use this new function object type by installing it
-as a combiner for our signal. The combiner template argument
-follows the signal's calling signature:</para>
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-<classname>boost::signal</classname>&lt;float (float x, float y),
- maximum&lt;float&gt; &gt; sig;
-</programlisting>
-</entry>
-<entry>
-<programlisting>
-<classname alt="boost::signalN">boost::signal2</classname>&lt;float, float, float,
- maximum&lt;float&gt; &gt; sig;
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
-<para>Now we can connect slots that perform arithmetic functions and
-use the signal:</para>
-<programlisting>
-sig.<methodname>connect</methodname>(&amp;quotient);
-sig.<methodname>connect</methodname>(&amp;product);
-sig.<methodname>connect</methodname>(&amp;sum);
-sig.<methodname>connect</methodname>(&amp;difference);
-
-std::cout &lt;&lt; sig(5, 3) &lt;&lt; std::endl;
-</programlisting>
-<para>The output of this program will be <code>15</code>, because
-regardless of the order in which the slots are connected, the product
-of 5 and 3 will be larger than the quotient, sum, or
-difference.</para>
-<para>In other cases we might want to return all of the values
-computed by the slots together, in one large data structure. This
-is easily done with a different combiner:</para>
-<programlisting>
-template&lt;typename Container&gt;
-struct aggregate_values
-{
- typedef Container result_type;
-
- template&lt;typename InputIterator&gt;
- Container operator()(InputIterator first, InputIterator last) const
- {
- return Container(first, last);
- }
-};
-</programlisting>
-<para>
-Again, we can create a signal with this new combiner:
-</para>
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-<classname>boost::signal</classname>&lt;float (float, float),
- aggregate_values&lt;std::vector&lt;float&gt; &gt; &gt; sig;
-
-sig.<methodname>connect</methodname>(&amp;quotient);
-sig.<methodname>connect</methodname>(&amp;product);
-sig.<methodname>connect</methodname>(&amp;sum);
-sig.<methodname>connect</methodname>(&amp;difference);
-
-std::vector&lt;float&gt; results = sig(5, 3);
-std::copy(results.begin(), results.end(),
- std::ostream_iterator&lt;float&gt;(cout, " "));
-</programlisting>
-</entry>
-<entry>
-<programlisting>
-<classname alt="boost::signalN">boost::signal2</classname>&lt;float, float, float,
- aggregate_values&lt;std::vector&lt;float&gt; &gt; &gt; sig;
-
-sig.<methodname>connect</methodname>(&amp;quotient);
-sig.<methodname>connect</methodname>(&amp;product);
-sig.<methodname>connect</methodname>(&amp;sum);
-sig.<methodname>connect</methodname>(&amp;difference);
-
-std::vector&lt;float&gt; results = sig(5, 3);
-std::copy(results.begin(), results.end(),
- std::ostream_iterator&lt;float&gt;(cout, " "));
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
-<para>The output of this program will contain 15, 8, 1.6667, and 2. It
-is interesting here that
-the first template argument for the <code>signal</code> class,
-<code>float</code>, is not actually the return type of the signal.
-Instead, it is the return type used by the connected slots and will
-also be the <code>value_type</code> of the input iterators passed
-to the combiner. The combiner itself is a function object and its
-<code>result_type</code> member type becomes the return type of the
-signal.</para>
-<para>The input iterators passed to the combiner transform dereference
-operations into slot calls. Combiners therefore have the option to
-invoke only some slots until some particular criterion is met. For
-instance, in a distributed computing system, the combiner may ask
-each remote system whether it will handle the request. Only one
-remote system needs to handle a particular request, so after a
-remote system accepts the work we do not want to ask any other
-remote systems to perform the same task. Such a combiner need only
-check the value returned when dereferencing the iterator, and
-return when the value is acceptable. The following combiner returns
-the first non-NULL pointer to a <code>FulfilledRequest</code> data
-structure, without asking any later slots to fulfill the
-request:</para>
-<programlisting>
-struct DistributeRequest {
- typedef FulfilledRequest* result_type;
-
- template&lt;typename InputIterator&gt;
- result_type operator()(InputIterator first, InputIterator last) const
- {
- while (first != last) {
- if (result_type fulfilled = *first)
- return fulfilled;
- ++first;
- }
- return 0;
- }
-};
-</programlisting>
-</section>
-</section>
-
-<section><title>Connection Management</title>
-<section><title>Disconnecting Slots (Beginner)</title>
-<para>Slots aren't expected to exist indefinately after they are
-connected. Often slots are only used to receive a few events and
-are then disconnected, and the programmer needs control to decide
-when a slot should no longer be connected.</para>
-<para>The entry point for managing connections explicitly is the
-<code><classname>boost::signals::connection</classname></code> class. The
-<code><classname>connection</classname></code> class uniquely represents the connection
-between a particular signal and a particular slot. The
-<code><methodname alt="connection::connected">connected</methodname>()</code> method checks if the signal and slot are
-still connected, and the <code><methodname alt="connection::disconnect">disconnect()</methodname></code> method
-disconnects the signal and slot if they are connected before it is
-called. Each call to the signal's <code>connect()</code> method
-returns a connection object, which can be used to determine if the
-connection still exists or to disconnect the signal and slot.</para>
-<programlisting>
-boost::signals::connection c = sig.<methodname>connect</methodname>(HelloWorld());
-if (c.<methodname>connected</methodname>()) {
-<emphasis>// c is still connected to the signal</emphasis>
- sig(); <emphasis>// Prints "Hello, World!"</emphasis>
-}
-
-c.disconnect(); <emphasis>// Disconnect the HelloWorld object</emphasis>
-assert(!c.<methodname>connected</methodname>()); <emphasis>c isn't connected any more</emphasis>
-
-sig(); <emphasis>// Does nothing: there are no connected slots</emphasis>
-</programlisting>
-</section>
-
-<section><title>Blocking Slots (Beginner)</title>
-
-<para>Slots can be temporarily "blocked", meaning that they will be
-ignored when the signal is invoked but have not been disconnected. A
-<classname>boost::signals::shared_connection_block</classname> object will
-temporarily block a slot. The connection is unblocked by either
-destroying or calling
-<methodname alt="shared_connection_block::unblock">unblock</methodname>
-on all the
-<code>shared_connection_block</code> objects that reference the connection.
-Here is an example of
-blocking/unblocking slots:</para>
-
-<programlisting>
-boost::signals::connection c = sig.<methodname>connect</methodname>(HelloWorld());
-sig(); <emphasis>// Prints "Hello, World!"</emphasis>
-
-{
- boost::signals::shared_connection_block block(c); <emphasis>// block the slot</emphasis>
- assert(c.<methodname>blocked</methodname>());
- sig(); <emphasis>// No output: the slot is blocked</emphasis>
-}<emphasis>// shared_connection_block going out of scope unblocks the slot</emphasis>
-sig(); <emphasis>// Prints "Hello, World!"</emphasis>
-</programlisting>
-
-</section>
-
-<section><title>Scoped connections (Intermediate)</title>
-<para>The <code>boost::signals::scoped_connection</code> class
-references a signal/slot connection that will be disconnected when
-the <code>scoped_connection</code> class goes out of scope. This
-ability is useful when a connection need only be temporary,
-e.g.,</para>
-<programlisting>
-{
- boost::signals::scoped_connection c = sig.<methodname>connect</methodname>(ShortLived());
- sig(); <emphasis>// will call ShortLived function object</emphasis>
-}
-sig(); <emphasis>// ShortLived function object no longer connected to sig</emphasis>
-</programlisting>
-</section>
-
-<section><title>Disconnecting equivalent slots (Intermediate)</title>
-<para>One can disconnect slots that are equivalent to a given function
-object using a form of the
-<code><methodname>disconnect</methodname></code> method, so long as
-the type of the function object has an accessible <code>==</code>
-operator. For instance:
-
-</para>
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-void foo();
-void bar();
-
-signal&lt;void()&gt; sig;
-
-sig.connect(&amp;foo);
-sig.connect(&amp;bar);
-
-// disconnects foo, but not bar
-sig.disconnect(&amp;foo);
-</programlisting>
-</entry>
-<entry>
-<programlisting>
-void foo();
-void bar();
-
-signal0&lt;void&gt; sig;
-
-sig.connect(&amp;foo);
-sig.connect(&amp;bar);
-
-// disconnects foo, but not bar
-sig.disconnect(&amp;foo);
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
-</section>
-
-<section><title>Automatic connection management (Intermediate)</title>
-<para>Boost.Signals can automatically track the lifetime of objects
-involved in signal/slot connections, including automatic
-disconnection of slots when objects involved in the slot call are
-destroyed. For instance, consider a simple news delivery service,
-where clients connect to a news provider that then sends news to
-all connected clients as information arrives. The news delivery
-service may be constructed like this: </para>
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-class NewsItem { /* ... */ };
-
-typedef boost::signal&lt;void (const NewsItem&amp;)&gt; signal_type;
-signal_type deliverNews;
-</programlisting>
-</entry>
-<entry>
-<programlisting>
-class NewsItem { /* ... */ };
-
-typedef boost::signal1&lt;void, const NewsItem&amp;&gt; signal_type;
-signal_type deliverNews;
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
-<para>Clients that wish to receive news updates need only connect a
-function object that can receive news items to the
-<code>deliverNews</code> signal. For instance, we may have a
-special message area in our application specifically for news,
-e.g.,:</para>
-<programlisting>
-struct NewsMessageArea : public MessageArea
-{
-public:
- // ...
-
- void displayNews(const NewsItem&amp; news) const
- {
- messageText = news.text();
- update();
- }
-};
-
-// ...
-NewsMessageArea *newsMessageArea = new NewsMessageArea(/* ... */);
-// ...
-deliverNews.<methodname>connect</methodname>(boost::bind(&amp;NewsMessageArea::displayNews,
- newsMessageArea, _1));
-</programlisting>
-<para>However, what if the user closes the news message area,
-destroying the <code>newsMessageArea</code> object that
-<code>deliverNews</code> knows about? Most likely, a segmentation
-fault will occur. However, with Boost.Signals one may track any object
-which is managed by a shared_ptr, by using
-<methodname alt="boost::slotN::track">slot::track</methodname>. A slot will automatically
-disconnect when any of its tracked objects expire. In
-addition, Boost.Signals will ensure that no tracked object expires
-while the slot it is associated with is in mid-execution. It does so by creating
-temporary shared_ptr copies of the slot's tracked objects before executing it.
-To track <code>NewsMessageArea</code>, we use a shared_ptr to manage
-its lifetime, and pass the shared_ptr to the slot via its
-<methodname alt="boost::slotN::track">slot::track</methodname>
-method before connecting it,
-e.g.:</para>
-<programlisting>
-// ...
-boost::shared_ptr&lt;NewsMessageArea&gt; newsMessageArea(new NewsMessageArea(/* ... */));
-// ...
-deliverNews.<methodname>connect</methodname>(signal_type::slot_type(&amp;NewsMessageArea::displayNews,
- newsMessageArea, _1).track(newsMessageArea));
-</programlisting>
-<para>Note there is no explicit call to bind() needed in the above example. If the
-<classname alt="slotN">slot</classname> constructor is passed more than one
-argument, it will automatically pass all the arguments to <code>bind</code> and use the
-returned function object.</para>
-<para>One limitation of using <code>shared_ptr</code> for tracking is that
-an object cannot setup tracking of itself in its constructor. However, it is
-possible to set up tracking in a post-constructor. In a post-constructor,
-a <code>shared_ptr</code> to <code>this</code> can be obtained by using
-<classname>enable_shared_from_this</classname>. You may also find
-<functionname>deconstruct_ptr</functionname> useful as a simple
-post-constructor/pre-destructor framework for your classes.
-</para>
-</section>
-
-<section><title>When can disconnections occur? (Intermediate)</title>
-<para>Signal/slot disconnections occur when any of these conditions
-occur:</para>
-<itemizedlist>
-<listitem><para>The connection is explicitly disconnected via the connection's
-<code>disconnect</code> method directly, or indirectly via the
-signal's <code>disconnect</code> method or
-<code>scoped_connection</code>'s destructor.</para></listitem>
-<listitem><para>An object tracked by the slot is
-destroyed.</para></listitem>
-<listitem><para>A slot throws an <classname>boost::expired_slot</classname> exception.
-</para></listitem>
-<listitem><para>The signal is destroyed.</para></listitem></itemizedlist>
-<para>These events can occur at any time without disrupting a signal's
-calling sequence. If a signal/slot connection is disconnected at
-any time during a signal's calling sequence, the calling sequence
-will still continue but will not invoke the disconnected slot.
-Additionally, a signal may be destroyed while it is in a calling
-sequence, and which case it will complete its slot call sequence
-but may not be accessed directly.</para>
-<para>Signals may be invoked recursively (e.g., a signal A calls a
-slot B that invokes signal A...). The disconnection behavior does
-not change in the recursive case, except that the slot calling
-sequence includes slot calls for all nested invocations of the
-signal.</para>
-</section>
-
-<section><title>Passing slots (Intermediate)</title>
-<para>Slots in the Boost.Signals library are created from arbitrary
-function objects, and therefore have no fixed type. However, it is
-commonplace to require that slots be passed through interfaces that
-cannot be templates. Slots can be passed via the
-<code>slot_type</code> for each particular signal type and any
-function object compatible with the signature of the signal can be
-passed to a <code>slot_type</code> parameter. For instance:</para>
- <informaltable>
- <tgroup cols="2" align="left">
- <thead>
- <row>
- <entry>Preferred syntax</entry>
- <entry>Portable syntax</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
-<programlisting>
-class Button
-{
- typedef boost::signal&lt;void (int x, int y)&gt; OnClick;
-
-public:
- void doOnClick(const OnClick::slot_type&amp; slot);
-
-private:
- OnClick onClick;
-};
-
-void Button::doOnClick(
- const OnClick::slot_type&amp; slot
- )
-{
- onClick.<methodname>connect</methodname>(slot);
-}
-
-void printCoordinates(long x, long y)
-{
- std::cout &lt;&lt; "(" &lt;&lt; x &lt;&lt; ", " &lt;&lt; y &lt;&lt; ")\n";
-}
-
-void f(Button&amp; button)
-{
- button.doOnClick(&amp;printCoordinates);
-}
-</programlisting>
-</entry>
-<entry>
-<programlisting>
-class Button
-{
- typedef <classname alt="boost::signalN">boost::signal2</classname>&lt;void,int,int&gt; OnClick;
-
-public:
- void doOnClick(const OnClick::slot_type&amp; slot);
-
-private:
- OnClick onClick;
-};
-
-void Button::doOnClick(
- const OnClick::slot_type&amp; slot
- )
-{
- onClick.<methodname>connect</methodname>(slot);
-}
-
-void printCoordinates(long x, long y)
-{
- std::cout &lt;&lt; "(" &lt;&lt; x &lt;&lt; ", " &lt;&lt; y &lt;&lt; ")\n";
-}
-
-void f(Button&amp; button)
-{
- button.doOnClick(&amp;printCoordinates);
-}
-</programlisting>
-</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
-<para>The <code>doOnClick</code> method is now functionally equivalent
-to the <code>connect</code> method of the <code>onClick</code>
-signal, but the details of the <code>doOnClick</code> method can be
-hidden in an implementation detail file.</para>
-</section>
-</section>
-
-<section>
- <title>Example: Document-View</title>
-
- <para>Signals can be used to implement flexible Document-View
- architectures. The document will contain a signal to which each of
- the views can connect. The following <code>Document</code> class
- defines a simple text document that supports mulitple views. Note
- that it stores a single signal to which all of the views will be
- connected.</para>
-
- <programlisting>class Document
-{
-public:
- typedef boost::signal&lt;void (bool)&gt; signal_t;
- typedef boost::signals::connection connection_t;
-
-public:
- Document()
- {}
-
- connection_t connect(signal_t::slot_function_type subscriber)
- {
- return m_sig.connect(subscriber);
- }
-
- void disconnect(connection_t subscriber)
- {
- subscriber.disconnect();
- }
-
- void append(const char* s)
- {
- m_text += s;
- m_sig(true);
- }
-
- const std::string&amp; getText() const
- {
- return m_text;
- }
-
-private:
- signal_t m_sig;
- std::string m_text;
-};</programlisting>
-
- <para>Next, we can define a <code>View</code> base class from which
- views can derive. This isn't strictly required, but it keeps the
- Document-View logic separate from the logic itself. Note that the
- constructor just connects the view to the document and the
- destructor disconnects the view.</para>
-
- <programlisting>
-class View
-{
-public:
- View(Document&amp; m)
- : m_document(m)
- {
- m_connection = m_document.connect(boost::bind(&amp;View::refresh, this, _1));
- }
-
- virtual ~View()
- {
- m_document.disconnect(m_connection);
- }
-
- virtual void refresh(bool bExtended) const = 0;
-
-protected:
- Document&amp; m_document;
-
-private:
- Document::connection_t m_connection;
-};
- </programlisting>
-
- <para>Finally, we can begin to define views. The
- following <code>TextView</code> class provides a simple view of the
- document text.</para>
-
- <programlisting>class TextView : public View
-{
-public:
- TextView(Document&amp; doc)
- : View(doc)
- {}
-
- virtual void refresh(bool bExtended) const
- {
- std::cout &lt;&lt; "TextView: " &lt;&lt; m_document.getText() &lt;&lt; std::endl;
- }
-};</programlisting>
-
- <para>Alternatively, we can provide a view of the document
- translated into hex values using the <code>HexView</code>
- view:</para>
-
- <programlisting>class HexView : public View
-{
-public:
- HexView(Document&amp; doc)
- : View(doc)
- {}
-
- virtual void refresh(bool bExtended) const
- {
- const std::string&amp; s = m_document.getText();
-
- std::cout &lt;&lt; "HexView:";
-
- for (std::string::const_iterator it = s.begin(); it != s.end(); ++it)
- std::cout &lt;&lt; ' ' &lt;&lt; std::hex &lt;&lt; static_cast&lt;int&gt;(*it);
-
- std::cout &lt;&lt; std::endl;
- }
-};</programlisting>
-
- <para>To tie the example together, here is a
- simple <code>main</code> function that sets up two views and then
- modifies the document:</para>
-
- <programlisting>int main(int argc, char* argv[])
-{
- Document doc;
- TextView v1(doc);
- HexView v2(doc);
-
- doc.append(argc == 2 ? argv[1] : "Hello world!");
- return 0;
-}</programlisting>
-
- <para>The complete example source, contributed by Keith MacDonald,
- is available in <ulink
- url="../../libs/signals/example/doc_view.cpp"><code>libs/signals/example/doc_view.cpp</code></ulink>.</para>
-</section>
-
-<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.
- </para>
-</section>
-
-</section>


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