| <?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: 2007-11-25 13:38:02 -0500 (Sun, 25 Nov 2007) $"> |
| <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><any, |
| connection></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<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> |