1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 2<html> 3<head> 4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 5<title>Design Rationale</title> 6<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css"> 7<meta name="generator" content="DocBook XSL Stylesheets V1.79.1"> 8<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset"> 9<link rel="up" href="../signals2.html" title="Chapter 35. Boost.Signals2"> 10<link rel="prev" href="faq.html" title="Frequently Asked Questions"> 11<link rel="next" href="api_changes.html" title="Signals2 API Changes"> 12</head> 13<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> 14<table cellpadding="2" width="100%"><tr> 15<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td> 16<td align="center"><a href="../../../index.html">Home</a></td> 17<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> 18<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td> 19<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td> 20<td align="center"><a href="../../../more/index.htm">More</a></td> 21</tr></table> 22<hr> 23<div class="spirit-nav"> 24<a accesskey="p" href="faq.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../signals2.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="api_changes.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> 25</div> 26<div class="section"> 27<div class="titlepage"><div><div><h2 class="title" style="clear: both"> 28<a name="signals2.rationale"></a>Design Rationale</h2></div></div></div> 29<div class="toc"><dl class="toc"> 30<dt><span class="section"><a href="rationale.html#id-1.3.36.9.2">User-level Connection Management</a></span></dt> 31<dt><span class="section"><a href="rationale.html#id-1.3.36.9.3">Automatic Connection Management</a></span></dt> 32<dt><span class="section"><a href="rationale.html#id-1.3.36.9.4"><code class="computeroutput">optional_last_value</code> as the Default Combiner</a></span></dt> 33<dt><span class="section"><a href="rationale.html#id-1.3.36.9.5">Combiner Interface</a></span></dt> 34<dt><span class="section"><a href="rationale.html#id-1.3.36.9.6">Connection Interfaces: += operator</a></span></dt> 35<dt><span class="section"><a href="rationale.html#id-1.3.36.9.7">Signals2 Mutex Classes</a></span></dt> 36<dt><span class="section"><a href="rationale.html#id-1.3.36.9.8">Comparison with other Signal/Slot implementations</a></span></dt> 37</dl></div> 38<div class="section"> 39<div class="titlepage"><div><div><h3 class="title"> 40<a name="id-1.3.36.9.2"></a>User-level Connection Management</h3></div></div></div> 41<p> Users need to have fine control over the connection of 42 signals to slots and their eventual disconnection. The primary approach 43 taken by Boost.Signals2 is to return a 44 <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> object that enables 45 connected/disconnected query, manual disconnection, and an 46 automatic disconnection on destruction mode (<code class="computeroutput"><a class="link" href="../boost/signals2/scoped_connection.html" title="Class scoped_connection">signals2::scoped_connection</a></code>). 47 In addition, two other interfaces are supported by the 48 <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_3-bb">signal::disconnect</a></code> overloaded method:</p> 49<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 50<li class="listitem"><p><span class="bold"><strong>Pass slot to 51 disconnect</strong></span>: in this interface model, the 52 disconnection of a slot connected with 53 <code class="computeroutput">sig.<a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_1-bb">connect</a>(typeof(sig)::slot_type(slot_func))</code> is 54 performed via 55 <code class="computeroutput">sig.<a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_3-bb">disconnect</a>(slot_func)</code>. Internally, 56 a linear search using slot comparison is performed and the 57 slot, if found, is removed from the list. Unfortunately, 58 querying connectedness ends up as a 59 linear-time operation.</p></li> 60<li class="listitem"> 61<p><span class="bold"><strong>Pass a token to 62 disconnect</strong></span>: this approach identifies slots with a 63 token that is easily comparable (e.g., a string), enabling 64 slots to be arbitrary function objects. While this approach is 65 essentially equivalent to the connection approach taken by Boost.Signals2, 66 it is possibly more error-prone for several reasons:</p> 67<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: circle; "> 68<li class="listitem"><p>Connections and disconnections must be paired, so 69 the problem becomes similar to the problems incurred when 70 pairing <code class="computeroutput">new</code> and <code class="computeroutput">delete</code> for 71 dynamic memory allocation. While errors of this sort would 72 not be catastrophic for a signals and slots 73 implementation, their detection is generally 74 nontrivial.</p></li> 75<li class="listitem"><p>If tokens are not unique, two slots may have 76 the same name and be indistinguishable. In 77 environments where many connections will be made 78 dynamically, name generation becomes an additional task 79 for the user.</p></li> 80</ul></div> 81<p> This type of interface is supported in Boost.Signals2 82 via the slot grouping mechanism, and the overload of 83 <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_3-bb">signal::disconnect</a></code> 84 which takes an argument of the signal's <code class="computeroutput">Group</code> type.</p> 85</li> 86</ul></div> 87</div> 88<div class="section"> 89<div class="titlepage"><div><div><h3 class="title"> 90<a name="id-1.3.36.9.3"></a>Automatic Connection Management</h3></div></div></div> 91<p>Automatic connection management in Signals2 92 depends on the use of <code class="computeroutput">boost::shared_ptr</code> to 93 manage the lifetimes of tracked objects. This is differs from 94 the original Boost.Signals library, which instead relied on derivation 95 from the <code class="computeroutput">boost::signals::trackable</code> class. 96 The library would be 97 notified of an object's destruction by the 98 <code class="computeroutput">boost::signals::trackable</code> destructor. 99 </p> 100<p>Unfortunately, the <code class="computeroutput">boost::signals::trackable</code> 101 scheme cannot be made thread safe due 102 to destructor ordering. The destructor of an class derived from 103 <code class="computeroutput">boost::signals::trackable</code> will always be 104 called before the destructor of the base <code class="computeroutput">boost::signals::trackable</code> 105 class. However, for thread-safety the connection between the signal and object 106 needs to be disconnected before the object runs its destructors. 107 Otherwise, if an object being destroyed 108 in one thread is connected to a signal concurrently 109 invoking in another thread, the signal may call into 110 a partially destroyed object. 111 </p> 112<p>We solve this problem by requiring that tracked objects be 113 managed by <code class="computeroutput">shared_ptr</code>. Slots keep a 114 <code class="computeroutput">weak_ptr</code> to every object the slot depends 115 on. Connections to a slot are disconnected when any of its tracked 116 <code class="computeroutput">weak_ptr</code>s expire. Additionally, signals 117 create their own temporary <code class="computeroutput">shared_ptr</code>s to 118 all of a slot's tracked objects prior to invoking the slot. This 119 insures none of the tracked objects destruct in mid-invocation. 120 </p> 121<p>The new connection management scheme has the advantage of being 122 non-intrusive. Objects of any type may be tracked using the 123 <code class="computeroutput">shared_ptr</code>/<code class="computeroutput">weak_ptr</code> scheme. The old 124 <code class="computeroutput">boost::signals::trackable</code> 125 scheme requires the tracked objects to be derived from the <code class="computeroutput">trackable</code> 126 base class, which is not always practical when interacting 127 with classes from 3rd party libraries. 128 </p> 129</div> 130<div class="section"> 131<div class="titlepage"><div><div><h3 class="title"> 132<a name="id-1.3.36.9.4"></a><code class="computeroutput">optional_last_value</code> as the Default Combiner</h3></div></div></div> 133<p> 134 The default combiner for Boost.Signals2 has changed from the <code class="computeroutput">last_value</code> 135 combiner used by default in the original Boost.Signals library. 136 This is because <code class="computeroutput">last_value</code> requires that at least 1 slot be 137 connected to the signal when it is invoked (except for the <code class="computeroutput">last_value<void></code> specialization). 138 In a multi-threaded environment where signal invocations and slot connections 139 and disconnections may be happening concurrently, it is difficult 140 to fulfill this requirement. When using <code class="computeroutput"><a class="link" href="../boost/signals2/optional_last_value.html" title="Class template optional_last_value">optional_last_value</a></code>, 141 there is no requirement for slots to be connected when a signal 142 is invoked, since in that case the combiner may simply return an empty 143 <code class="computeroutput">boost::optional</code>. 144 </p> 145</div> 146<div class="section"> 147<div class="titlepage"><div><div><h3 class="title"> 148<a name="id-1.3.36.9.5"></a>Combiner Interface</h3></div></div></div> 149<p> The Combiner interface was chosen to mimic a call to an 150 algorithm in the C++ standard library. It is felt that by viewing 151 slot call results as merely a sequence of values accessed by input 152 iterators, the combiner interface would be most natural to a 153 proficient C++ programmer. Competing interface design generally 154 required the combiners to be constructed to conform to an 155 interface that would be customized for (and limited to) the 156 Signals2 library. While these interfaces are generally enable more 157 straighforward implementation of the signals & slots 158 libraries, the combiners are unfortunately not reusable (either in 159 other signals & slots libraries or within other generic 160 algorithms), and the learning curve is steepened slightly to learn 161 the specific combiner interface.</p> 162<p> The Signals2 formulation of combiners is based on the 163 combiner using the "pull" mode of communication, instead of the 164 more complex "push" mechanism. With a "pull" mechanism, the 165 combiner's state can be kept on the stack and in the program 166 counter, because whenever new data is required (i.e., calling the 167 next slot to retrieve its return value), there is a simple 168 interface to retrieve that data immediately and without returning 169 from the combiner's code. Contrast this with the "push" mechanism, 170 where the combiner must keep all state in class members because 171 the combiner's routines will be invoked for each signal 172 called. Compare, for example, a combiner that returns the maximum 173 element from calling the slots. If the maximum element ever 174 exceeds 100, no more slots are to be called.</p> 175<div class="informaltable"><table class="table"> 176<colgroup> 177<col> 178<col> 179</colgroup> 180<thead><tr> 181<th align="left"><p>Pull</p></th> 182<th align="left"><p>Push</p></th> 183</tr></thead> 184<tbody><tr> 185<td align="left"> 186<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"> 187struct pull_max { 188 typedef int result_type; 189 190 template<typename InputIterator> 191 result_type operator()(InputIterator first, 192 InputIterator last) 193 { 194 if (first == last) 195 throw std::runtime_error("Empty!"); 196 197 int max_value = *first++; 198 while(first != last && *first <= 100) { 199 if (*first > max_value) 200 max_value = *first; 201 ++first; 202 } 203 204 return max_value; 205 } 206}; 207</pre> 208</td> 209<td align="left"> 210<pre xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" class="table-programlisting"> 211struct push_max { 212 typedef int result_type; 213 214 push_max() : max_value(), got_first(false) {} 215 216 // returns false when we want to stop 217 bool operator()(int result) { 218 if (result > 100) 219 return false; 220 221 if (!got_first) { 222 got_first = true; 223 max_value = result; 224 return true; 225 } 226 227 if (result > max_value) 228 max_value = result; 229 230 return true; 231 } 232 233 int get_value() const 234 { 235 if (!got_first) 236 throw std::runtime_error("Empty!"); 237 return max_value; 238 } 239 240private: 241 int max_value; 242 bool got_first; 243}; 244</pre> 245</td> 246</tr></tbody> 247</table></div> 248<p>There are several points to note in these examples. The 249 "pull" version is a reusable function object that is based on an 250 input iterator sequence with an integer <code class="computeroutput">value_type</code>, 251 and is very straightforward in design. The "push" model, on the 252 other hand, relies on an interface specific to the caller and is 253 not generally reusable. It also requires extra state values to 254 determine, for instance, if any elements have been 255 received. Though code quality and ease-of-use is generally 256 subjective, the "pull" model is clearly shorter and more reusable 257 and will often be construed as easier to write and understand, 258 even outside the context of a signals & slots library.</p> 259<p> The cost of the "pull" combiner interface is paid in the 260 implementation of the Signals2 library itself. To correctly handle 261 slot disconnections during calls (e.g., when the dereference 262 operator is invoked), one must construct the iterator to skip over 263 disconnected slots. Additionally, the iterator must carry with it 264 the set of arguments to pass to each slot (although a reference to 265 a structure containing those arguments suffices), and must cache 266 the result of calling the slot so that multiple dereferences don't 267 result in multiple calls. This apparently requires a large degree 268 of overhead, though if one considers the entire process of 269 invoking slots one sees that the overhead is nearly equivalent to 270 that in the "push" model, but we have inverted the control 271 structures to make iteration and dereference complex (instead of 272 making combiner state-finding complex).</p> 273</div> 274<div class="section"> 275<div class="titlepage"><div><div><h3 class="title"> 276<a name="id-1.3.36.9.6"></a>Connection Interfaces: += operator</h3></div></div></div> 277<p> Boost.Signals2 supports a connection syntax with the form 278 <code class="computeroutput">sig.<a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_1-bb">connect</a>(slot)</code>, but a 279 more terse syntax <code class="computeroutput">sig += slot</code> has been suggested (and 280 has been used by other signals & slots implementations). There 281 are several reasons as to why this syntax has been 282 rejected:</p> 283<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 284<li class="listitem"><p><span class="bold"><strong>It's unnecessary</strong></span>: the 285 connection syntax supplied by Boost.Signals2 is no less 286 powerful that that supplied by the <code class="computeroutput">+=</code> 287 operator. The savings in typing (<code class="computeroutput">connect()</code> 288 vs. <code class="computeroutput">+=</code>) is essentially negligible. Furthermore, 289 one could argue that calling <code class="computeroutput">connect()</code> is more 290 readable than an overload of <code class="computeroutput">+=</code>.</p></li> 291<li class="listitem"><p><span class="bold"><strong>Ambiguous return type</strong></span>: 292 there is an ambiguity concerning the return value of the 293 <code class="computeroutput">+=</code> operation: should it be a reference to the 294 signal itself, to enable <code class="computeroutput">sig += slot1 += slot2</code>, 295 or should it return a 296 <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> for the 297 newly-created signal/slot connection?</p></li> 298<li class="listitem"> 299<p><span class="bold"><strong>Gateway to operators -=, 300 +</strong></span>: when one has added a connection operator 301 <code class="computeroutput">+=</code>, it seems natural to have a disconnection 302 operator <code class="computeroutput">-=</code>. However, this presents problems when 303 the library allows arbitrary function objects to implicitly 304 become slots, because slots are no longer comparable. </p> 305<p> The second obvious addition when one has 306 <code class="computeroutput">operator+=</code> would be to add a <code class="computeroutput">+</code> 307 operator that supports addition of multiple slots, followed by 308 assignment to a signal. However, this would require 309 implementing <code class="computeroutput">+</code> such that it can accept any two 310 function objects, which is technically infeasible.</p> 311</li> 312</ul></div> 313</div> 314<div class="section"> 315<div class="titlepage"><div><div><h3 class="title"> 316<a name="id-1.3.36.9.7"></a>Signals2 Mutex Classes</h3></div></div></div> 317<p> 318 The Boost.Signals2 library provides 2 mutex classes: <code class="computeroutput"><a class="link" href="../boost/signals2/mutex.html" title="Class mutex">boost::signals2::mutex</a></code>, 319 and <code class="computeroutput"><a class="link" href="../boost/signals2/dummy_mutex.html" title="Class dummy_mutex">boost::signals2::dummy_mutex</a></code>. The motivation for providing 320 <code class="computeroutput"><a class="link" href="../boost/signals2/mutex.html" title="Class mutex">boost::signals2::mutex</a></code> is simply that the <code class="computeroutput">boost::mutex</code> 321 class provided by the Boost.Thread library currently requires linking to libboost_thread. 322 The <code class="computeroutput"><a class="link" href="../boost/signals2/mutex.html" title="Class mutex">boost::signals2::mutex</a></code> class allows Signals2 to remain 323 a header-only library. You may still choose to use <code class="computeroutput">boost::mutex</code> 324 if you wish, by specifying it as the <code class="computeroutput">Mutex</code> template type for your signals. 325 </p> 326<p> 327 The <code class="computeroutput"><a class="link" href="../boost/signals2/dummy_mutex.html" title="Class dummy_mutex">boost::signals2::dummy_mutex</a></code> class is provided to allow 328 performance sensitive single-threaded applications to minimize overhead by avoiding unneeded 329 mutex locking. 330 </p> 331</div> 332<div class="section"> 333<div class="titlepage"><div><div><h3 class="title"> 334<a name="id-1.3.36.9.8"></a>Comparison with other Signal/Slot implementations</h3></div></div></div> 335<div class="toc"><dl class="toc"> 336<dt><span class="section"><a href="rationale.html#id-1.3.36.9.8.2">libsigc++</a></span></dt> 337<dt><span class="section"><a href="rationale.html#id-1.3.36.9.8.3">.NET delegates</a></span></dt> 338</dl></div> 339<div class="section"> 340<div class="titlepage"><div><div><h4 class="title"> 341<a name="id-1.3.36.9.8.2"></a>libsigc++</h4></div></div></div> 342<p> <a href="http://libsigc.sourceforge.net" target="_top">libsigc++</a> is a C++ 343 signals & slots library that originally started as part of 344 an initiative to wrap the C interfaces to <a href="http://www.gtk.org" target="_top">GTK</a> libraries in C++, and has 345 grown to be a separate library maintained by Karl Nelson. There 346 are many similarities between libsigc++ and Boost.Signals2, and 347 indeed the original Boost.Signals was strongly influenced by 348 Karl Nelson and libsigc++. A cursory inspection of each library will find a 349 similar syntax for the construction of signals and in the use of 350 connections. There 351 are some major differences in design that separate these 352 libraries:</p> 353<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 354<li class="listitem"><p><span class="bold"><strong>Slot definitions</strong></span>: 355 slots in libsigc++ are created using a set of primitives 356 defined by the library. These primitives allow binding of 357 objects (as part of the library), explicit adaptation from 358 the argument and return types of the signal to the argument 359 and return types of the slot (libsigc++ is, by default, more 360 strict about types than Boost.Signals2).</p></li> 361<li class="listitem"><p><span class="bold"><strong>Combiner/Marshaller 362 interface</strong></span>: the equivalent to Boost.Signals2 363 combiners in libsigc++ are the marshallers. Marshallers are 364 similar to the "push" interface described in Combiner 365 Interface, and a proper treatment of the topic is given 366 there.</p></li> 367</ul></div> 368</div> 369<div class="section"> 370<div class="titlepage"><div><div><h4 class="title"> 371<a name="id-1.3.36.9.8.3"></a>.NET delegates</h4></div></div></div> 372<p> <a href="http://www.microsoft.com" target="_top">Microsoft</a> 373 has introduced the .NET Framework and an associated set of 374 languages and language extensions, one of which is the 375 delegate. Delegates are similar to signals and slots, but they 376 are more limited than most C++ signals and slots implementations 377 in that they:</p> 378<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 379<li class="listitem"><p>Require exact type matches between a delegate and what 380 it is calling.</p></li> 381<li class="listitem"><p>Only return the result of the last target called, with no option for customization.</p></li> 382<li class="listitem"><p>Must call a method with <code class="computeroutput">this</code> already 383 bound.</p></li> 384</ul></div> 385</div> 386</div> 387</div> 388<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 389<td align="left"><p><small>Last revised: June 12, 2007 at 14:01:23 -0400</small></p></td> 390<td align="right"><div class="copyright-footer">Copyright © 2001-2004 Douglas Gregor<br>Copyright © 2007-2009 Frank Mori Hess<p>Distributed under the Boost 391 Software License, Version 1.0. (See accompanying file 392 <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> 393</div></td> 394</tr></table> 395<hr> 396<div class="spirit-nav"> 397<a accesskey="p" href="faq.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../signals2.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="api_changes.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> 398</div> 399</body> 400</html> 401