Imported Upstream version 1.57.0
[platform/upstream/boost.git] / doc / html / signals / s06.html
1 <html>
2 <head>
3 <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
4 <title>Design Rationale</title>
5 <link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
6 <meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
7 <link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
8 <link rel="up" href="../signals.html" title="Chapter&#160;26.&#160;Boost.Signals">
9 <link rel="prev" href="s05.html" title="Design Overview">
10 <link rel="next" href="tests.html" title="Testsuite">
11 </head>
12 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13 <table cellpadding="2" width="100%"><tr>
14 <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
15 <td align="center"><a href="../../../index.html">Home</a></td>
16 <td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
17 <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18 <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19 <td align="center"><a href="../../../more/index.htm">More</a></td>
20 </tr></table>
21 <hr>
22 <div class="spirit-nav">
23 <a accesskey="p" href="s05.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../signals.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tests.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
24 </div>
25 <div class="section">
26 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
27 <a name="idp426577568"></a>Design Rationale</h2></div></div></div>
28 <div class="toc"><dl class="toc">
29 <dt><span class="section"><a href="s06.html#idp426578544">Choice of Slot Definitions</a></span></dt>
30 <dt><span class="section"><a href="s06.html#idp426587936">User-level Connection Management</a></span></dt>
31 <dt><span class="section"><a href="s06.html#idp426606192">Combiner Interface</a></span></dt>
32 <dt><span class="section"><a href="s06.html#idp426621280">Connection Interfaces: +=  operator</a></span></dt>
33 <dt><span class="section"><a href="s06.html#idp426640656"><code class="computeroutput">trackable</code> rationale</a></span></dt>
34 <dt><span class="section"><a href="s06.html#idp426660768">Comparison with other Signal/Slot implementations</a></span></dt>
35 </dl></div>
36 <div class="section">
37 <div class="titlepage"><div><div><h3 class="title">
38 <a name="idp426578544"></a>Choice of Slot Definitions</h3></div></div></div>
39 <p> The definition of a slot differs amongst signals and slots
40     libraries. Within Boost.Signals, a slot is defined in a very loose
41     manner: it can be any function object that is callable given
42     parameters of the types specified by the signal, and whose return
43     value is convertible to the result type expected by the
44     signal. However, alternative definitions have associated pros and
45     cons that were considered prior to the construction of
46     Boost.Signals.</p>
47 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
48 <li class="listitem">
49 <p><span class="bold"><strong>Slots derive from a specific base
50         class</strong></span>: generally a scheme such as this will require
51         all user-defined slots to derive from some library-specified
52         <code class="computeroutput">Slot</code> abstract class that defines a virtual
53         function calling the slot. Adaptors can be used to convert a
54         definition such as this to a definition similar to that used
55         by Boost.Signals, but the use of a large number of small
56         adaptor classes containing virtual functions has been found to
57         cause an unacceptable increase in the size of executables
58         (polymorphic class types require more code than
59         non-polymorphic types).</p>
60 <p> This approach does have the benefit of simplicity of
61         implementation and user interface, from an object-oriented
62         perspective.</p>
63 </li>
64 <li class="listitem"><p><span class="bold"><strong>Slots constructed from a set of
65         primitives</strong></span>: in this scheme the slot can have a
66         limited set of types (often derived from a common abstract
67         base class) that are constructed from some library-defined set
68         of primitives that often include conversions from free
69         function pointers and member function pointers, and a limited
70         set of binding capabilities. Such an approach is reasonably
71         simple and cover most common cases, but it does not allow a
72         large degree of flexibility in slot construction. Libraries
73         for function object composition have become quite advanced and
74         it is out of the scope of a signals and slots library to
75         encorporate such enhancements. Thus Boost.Signals does not
76         include argument binding or function object composition
77         primitives, but instead provides a hook (via the
78         <code class="computeroutput"><a class="link" href="../boost/visit_each.html" title="Function template visit_each">visit_each</a></code>
79         mechanism) that allows existing binder/composition libraries
80         to provide the necessary information to Signals.</p></li>
81 </ul></div>
82 <p> Users not satisfied with the slot definition choice may opt
83     to replace the default slot function type with an alternative that
84     meets their specific needs.</p>
85 </div>
86 <div class="section">
87 <div class="titlepage"><div><div><h3 class="title">
88 <a name="idp426587936"></a>User-level Connection Management</h3></div></div></div>
89 <p> Users need to have fine control over the connection of
90     signals to slots and their eventual disconnection. The approach
91     taken by Boost.Signals is to return a
92     <code class="computeroutput"><a class="link" href="../boost/signals/connection.html" title="Class connection">connection</a></code> object that enables
93     connected/disconnected query, manual disconnection, and an
94     automatic disconnection on destruction mode. Some other possible
95     interfaces include:</p>
96 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
97 <li class="listitem"><p><span class="bold"><strong>Pass slot to
98         disconnect</strong></span>: in this interface model, the
99         disconnection of a slot connected with
100         <code class="computeroutput">sig.<a class="link" href="../boost/signalN.html#idp146240304-bb">connect</a>(slot)</code> is
101         performed via
102         <code class="computeroutput">sig.<a class="link" href="../boost/signalN.html#idp211498240-bb">disconnect</a>(slot)</code>. Internally,
103         a linear search using slot comparison is performed and the
104         slot, if found, is removed from the list. Unfortunately,
105         querying connectedness will generally also end up as
106         linear-time operations. This model also fails for
107         implementation reasons when slots become more complex than
108         simple function pointers, member function pointers and a
109         limited set of compositions and argument binders: to match the
110         slot given in the call to
111         <code class="computeroutput"><a class="link" href="../boost/signalN.html#idp211498240-bb">disconnect</a></code> with an
112         existing slot we would need to be able to compare arbitrary
113         function objects, which is not feasible.</p></li>
114 <li class="listitem">
115 <p><span class="bold"><strong>Pass a token to
116         disconnect</strong></span>: this approach identifies slots with a
117         token that is easily comparable (e.g., a string), enabling
118         slots to be arbitrary function objects. While this approach is
119         essentially equivalent to the approach taken by Boost.Signals,
120         it is possibly more error-prone for several reasons:</p>
121 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; ">
122 <li class="listitem"><p>Connections and disconnections must be paired, so
123             the problem becomes similar to the problems incurred when
124             pairing <code class="computeroutput">new</code> and <code class="computeroutput">delete</code> for
125             dynamic memory allocation. While errors of this sort would
126             not be catastrophic for a signals and slots
127             implementation, their detection is generally
128             nontrivial.</p></li>
129 <li class="listitem"><p>Tokens must be unique, otherwise two slots will have
130             the same name and will be indistinguishable. In
131             environments where many connections will be made
132             dynamically, name generation becomes an additional task
133             for the user. Uniqueness of tokens also results in an
134             additional failure mode when attempting to connect a slot
135             using a token that has already been used.</p></li>
136 <li class="listitem"><p>More parameterization would be required, because the
137             token type must be user-defined. Additional
138             parameterization steepens the learning curver and
139             overcomplicates a simple interface.</p></li>
140 </ul></div>
141 <p> This type of interface is supported in Boost.Signals
142         via the slot grouping mechanism. It augments the
143         <code class="computeroutput"><a class="link" href="../boost/signals/connection.html" title="Class connection">connection</a></code> object-based
144         connection management scheme.</p>
145 </li>
146 </ul></div>
147 </div>
148 <div class="section">
149 <div class="titlepage"><div><div><h3 class="title">
150 <a name="idp426606192"></a>Combiner Interface</h3></div></div></div>
151 <p> The Combiner interface was chosen to mimic a call to an
152     algorithm in the C++ standard library. It is felt that by viewing
153     slot call results as merely a sequence of values accessed by input
154     iterators, the combiner interface would be most natural to a
155     proficient C++ programmer. Competing interface design generally
156     required the combiners to be constructed to conform to an
157     interface that would be customized for (and limited to) the
158     Signals library. While these interfaces are generally enable more
159     straighforward implementation of the signals &amp; slots
160     libraries, the combiners are unfortunately not reusable (either in
161     other signals &amp; slots libraries or within other generic
162     algorithms), and the learning curve is steepened slightly to learn
163     the specific combiner interface.</p>
164 <p> The Signals formulation of combiners is based on the
165     combiner using the "pull" mode of communication, instead of the
166     more complex "push" mechanism. With a "pull" mechanism, the
167     combiner's state can be kept on the stack and in the program
168     counter, because whenever new data is required (i.e., calling the
169     next slot to retrieve its return value), there is a simple
170     interface to retrieve that data immediately and without returning
171     from the combiner's code. Contrast this with the "push" mechanism,
172     where the combiner must keep all state in class members because
173     the combiner's routines will be invoked for each signal
174     called. Compare, for example, a combiner that returns the maximum
175     element from calling the slots. If the maximum element ever
176     exceeds 100, no more slots are to be called.</p>
177 <div class="informaltable"><table class="table">
178 <colgroup>
179 <col>
180 <col>
181 </colgroup>
182 <thead><tr>
183 <th align="left"><p>Pull</p></th>
184 <th align="left"><p>Push</p></th>
185 </tr></thead>
186 <tbody><tr>
187 <td align="left">
188 <pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting">
189 struct pull_max {
190   typedef int result_type;
191
192   template&lt;typename InputIterator&gt;
193   result_type operator()(InputIterator first,
194                          InputIterator last)
195   {
196     if (first == last)
197       throw std::runtime_error("Empty!");
198
199     int max_value = *first++;
200     while(first != last &amp;&amp; *first &lt;= 100) {
201       if (*first &gt; max_value)
202         max_value = *first;
203       ++first;
204     }
205
206     return max_value;
207   }
208 };
209 </pre>
210 </td>
211 <td align="left">
212 <pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting">
213 struct push_max {
214   typedef int result_type;
215
216   push_max() : max_value(), got_first(false) {}
217
218   // returns false when we want to stop
219   bool operator()(int result) {
220     if (result &gt; 100)
221       return false;
222
223     if (!got_first) {
224       got_first = true;
225       max_value = result;
226       return true;
227     }
228
229     if (result &gt; max_value)
230       max_value = result;
231
232     return true;
233   }
234
235   int get_value() const 
236   { 
237     if (!got_first)
238       throw std::runtime_error("Empty!");
239     return max_value; 
240   }
241
242 private:
243   int  max_value; 
244   bool got_first;
245 };
246 </pre>
247 </td>
248 </tr></tbody>
249 </table></div>
250 <p>There are several points to note in these examples. The
251     "pull" version is a reusable function object that is based on an
252     input iterator sequence with an integer <code class="computeroutput">value_type</code>,
253     and is very straightforward in design. The "push" model, on the
254     other hand, relies on an interface specific to the caller and is
255     not generally reusable. It also requires extra state values to
256     determine, for instance, if any elements have been
257     received. Though code quality and ease-of-use is generally
258     subjective, the "pull" model is clearly shorter and more reusable
259     and will often be construed as easier to write and understand,
260     even outside the context of a signals &amp; slots library.</p>
261 <p> The cost of the "pull" combiner interface is paid in the
262     implementation of the Signals library itself. To correctly handle
263     slot disconnections during calls (e.g., when the dereference
264     operator is invoked), one must construct the iterator to skip over
265     disconnected slots. Additionally, the iterator must carry with it
266     the set of arguments to pass to each slot (although a reference to
267     a structure containing those arguments suffices), and must cache
268     the result of calling the slot so that multiple dereferences don't
269     result in multiple calls. This apparently requires a large degree
270     of overhead, though if one considers the entire process of
271     invoking slots one sees that the overhead is nearly equivalent to
272     that in the "push" model, but we have inverted the control
273     structures to make iteration and dereference complex (instead of
274     making combiner state-finding complex).</p>
275 </div>
276 <div class="section">
277 <div class="titlepage"><div><div><h3 class="title">
278 <a name="idp426621280"></a>Connection Interfaces: +=  operator</h3></div></div></div>
279 <p> Boost.Signals supports a connection syntax with the form
280     <code class="computeroutput">sig.<a class="link" href="../boost/signalN.html#idp146240304-bb">connect</a>(slot)</code>, but a
281     more terse syntax <code class="computeroutput">sig += slot</code> has been suggested (and
282     has been used by other signals &amp; slots implementations). There
283     are several reasons as to why this syntax has been
284     rejected:</p>
285 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
286 <li class="listitem"><p><span class="bold"><strong>It's unnecessary</strong></span>: the
287         connection syntax supplied by Boost.Signals is no less
288         powerful that that supplied by the <code class="computeroutput">+=</code>
289         operator. The savings in typing (<code class="computeroutput">connect()</code>
290         vs. <code class="computeroutput">+=</code>) is essentially negligible. Furthermore,
291         one could argue that calling <code class="computeroutput">connect()</code> is more
292         readable than an overload of <code class="computeroutput">+=</code>.</p></li>
293 <li class="listitem"><p><span class="bold"><strong>Ambiguous return type</strong></span>:
294         there is an ambiguity concerning the return value of the
295         <code class="computeroutput">+=</code> operation: should it be a reference to the
296         signal itself, to enable <code class="computeroutput">sig += slot1 += slot2</code>,
297         or should it return a
298         <code class="computeroutput"><a class="link" href="../boost/signals/connection.html" title="Class connection">connection</a></code> for the
299         newly-created signal/slot connection?</p></li>
300 <li class="listitem">
301 <p><span class="bold"><strong>Gateway to operators -=,
302         +</strong></span>: when one has added a connection operator
303         <code class="computeroutput">+=</code>, it seems natural to have a disconnection
304         operator <code class="computeroutput">-=</code>. However, this presents problems when
305         the library allows arbitrary function objects to implicitly
306         become slots, because slots are no longer comparable.  </p>
307 <p> The second obvious addition when one has
308         <code class="computeroutput">operator+=</code> would be to add a <code class="computeroutput">+</code>
309         operator that supports addition of multiple slots, followed by
310         assignment to a signal. However, this would require
311         implementing <code class="computeroutput">+</code> such that it can accept any two
312         function objects, which is technically infeasible.</p>
313 </li>
314 </ul></div>
315 </div>
316 <div class="section">
317 <div class="titlepage"><div><div><h3 class="title">
318 <a name="idp426640656"></a><code class="computeroutput">trackable</code> rationale</h3></div></div></div>
319 <div class="toc"><dl class="toc">
320 <dt><span class="section"><a href="s06.html#idp426645280"><code class="computeroutput">trackable</code> copying behavior</a></span></dt>
321 <dt><span class="section"><a href="s06.html#idp426651440">Why derivation from <code class="computeroutput">trackable</code>?</a></span></dt>
322 </dl></div>
323 <p> The <code class="computeroutput"><a class="link" href="../boost/signals/trackable.html" title="Class trackable">trackable</a></code>
324       class is the primary user interface to automatic connection
325       lifetime management, and its design affects users directly. Two
326       issues stick out most: the odd copying behavior of
327       <code class="computeroutput">trackable</code>, and the limitation requiring users to
328       derive from <code class="computeroutput">trackable</code> to create types that can
329       participate in automatic connection management.</p>
330 <div class="section">
331 <div class="titlepage"><div><div><h4 class="title">
332 <a name="idp426645280"></a><code class="computeroutput">trackable</code> copying behavior</h4></div></div></div>
333 <p> The copying behavior of
334       <code class="computeroutput"><a class="link" href="../boost/signals/trackable.html" title="Class trackable">trackable</a></code> is essentially
335       that <code class="computeroutput"><a class="link" href="../boost/signals/trackable.html" title="Class trackable">trackable</a></code> subobjects
336       are never copied; instead, the copy operation is merely a
337       no-op. To understand this, we look at the nature of a
338       signal-slot connection and note that the connection is based on
339       the entities that are being connected; when one of the entities
340       is destroyed, the connection is destroyed. Therefore, when a
341       <code class="computeroutput"><a class="link" href="../boost/signals/trackable.html" title="Class trackable">trackable</a></code> subobject is
342       copied, we cannot copy the connections because the connections
343       don't refer to the target entity - they refer to the source
344       entity. This reason is dual to the reason signals are
345       noncopyable: the slots connected to them are connected to that
346       particular signal, not the data contained in the signal.</p>
347 </div>
348 <div class="section">
349 <div class="titlepage"><div><div><h4 class="title">
350 <a name="idp426651440"></a>Why derivation from <code class="computeroutput">trackable</code>?</h4></div></div></div>
351 <p> For <code class="computeroutput"><a class="link" href="../boost/signals/trackable.html" title="Class trackable">trackable</a></code> to work
352       properly, there are two constraints:</p>
353 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
354 <li class="listitem"><p><code class="computeroutput"><a class="link" href="../boost/signals/trackable.html" title="Class trackable">trackable</a></code> must
355           have storage space to keep track of all connections made to
356           this object.</p></li>
357 <li class="listitem"><p><code class="computeroutput"><a class="link" href="../boost/signals/trackable.html" title="Class trackable">trackable</a></code> must be
358           notified when the object is being destructed so that it can
359           disconnect its connections.</p></li>
360 </ul></div>
361 <p>Clearly, deriving from
362       <code class="computeroutput"><a class="link" href="../boost/signals/trackable.html" title="Class trackable">trackable</a></code> meets these two
363       guidelines. We have not yet found a superior solution.</p>
364 </div>
365 </div>
366 <div class="section">
367 <div class="titlepage"><div><div><h3 class="title">
368 <a name="idp426660768"></a>Comparison with other Signal/Slot implementations</h3></div></div></div>
369 <div class="toc"><dl class="toc">
370 <dt><span class="section"><a href="s06.html#idp426661472">libsigc++</a></span></dt>
371 <dt><span class="section"><a href="s06.html#idp426668816">.NET delegates</a></span></dt>
372 </dl></div>
373 <div class="section">
374 <div class="titlepage"><div><div><h4 class="title">
375 <a name="idp426661472"></a>libsigc++</h4></div></div></div>
376 <p> <a href="http://libsigc.sourceforge.net" target="_top">libsigc++</a> is a C++
377       signals &amp; slots library that originally started as part of
378       an initiative to wrap the C interfaces to <a href="http://www.gtk.org" target="_top">GTK</a> libraries in C++, and has
379       grown to be a separate library maintained by Karl Nelson. There
380       are many similarities between libsigc++ and Boost.Signals, and
381       indeed Boost.Signals was strongly influenced by Karl Nelson and
382       libsigc++. A cursory inspection of each library will find a
383       similar syntax for the construction of signals and in the use of
384       connections and automatic connection lifetime management. There
385       are some major differences in design that separate these
386       libraries:</p>
387 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
388 <li class="listitem"><p><span class="bold"><strong>Slot definitions</strong></span>:
389           slots in libsigc++ are created using a set of primitives
390           defined by the library. These primitives allow binding of
391           objects (as part of the library), explicit adaptation from
392           the argument and return types of the signal to the argument
393           and return types of the slot (libsigc++ is, by default, more
394           strict about types than Boost.Signals). A discussion of this
395           approach with a comparison against the approach taken by
396           Boost.Signals is given in Choice of Slot Definitions.</p></li>
397 <li class="listitem"><p><span class="bold"><strong>Combiner/Marshaller
398           interface</strong></span>: the equivalent to Boost.Signals
399           combiners in libsigc++ are the marshallers. Marshallers are
400           similar to the "push" interface described in Combiner
401           Interface, and a proper treatment of the topic is given
402           there.</p></li>
403 </ul></div>
404 </div>
405 <div class="section">
406 <div class="titlepage"><div><div><h4 class="title">
407 <a name="idp426668816"></a>.NET delegates</h4></div></div></div>
408 <p> <a href="http://www.microsoft.com" target="_top">Microsoft</a>
409       has introduced the .NET Framework and an associated set of
410       languages and language extensions, one of which is the
411       delegate. Delegates are similar to signals and slots, but they
412       are more limited than most C++ signals and slots implementations
413       in that they:</p>
414 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
415 <li class="listitem"><p>Require exact type matches between a delegate and what
416           it is calling.</p></li>
417 <li class="listitem"><p>Only return the result of the last target called, with no option for customization.</p></li>
418 <li class="listitem"><p>Must call a method with <code class="computeroutput">this</code> already
419           bound.</p></li>
420 </ul></div>
421 </div>
422 </div>
423 </div>
424 <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
425 <td align="left"></td>
426 <td align="right"><div class="copyright-footer">Copyright &#169; 2001-2004 Douglas Gregor<p>Use, modification and distribution is subject to the Boost
427     Software License, Version 1.0. (See accompanying file
428     <code class="filename">LICENSE_1_0.txt</code> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)</p>
429 </div></td>
430 </tr></table>
431 <hr>
432 <div class="spirit-nav">
433 <a accesskey="p" href="s05.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../signals.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="tests.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
434 </div>
435 </body>
436 </html>