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>Tutorial</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="../signals2.html" title="Chapter 35. Boost.Signals2"> 11<link rel="next" href="examples.html" title="Example programs"> 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="../signals2.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="examples.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.tutorial"></a>Tutorial</h2></div></div></div> 29<div class="toc"><dl class="toc"> 30<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.2">How to Read this Tutorial</a></span></dt> 31<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.3">Hello, World! (Beginner)</a></span></dt> 32<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.4">Calling Multiple Slots</a></span></dt> 33<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.5">Passing Values to and from Slots</a></span></dt> 34<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.6">Connection Management</a></span></dt> 35<dt><span class="section"><a href="tutorial.html#signals2.tutorial.document-view">Example: Document-View</a></span></dt> 36<dt><span class="section"><a href="tutorial.html#signals2.tutorial.extended-slot-type">Giving a Slot Access to its Connection (Advanced)</a></span></dt> 37<dt><span class="section"><a href="tutorial.html#signals2.tutorial.signal-mutex-template-parameter">Changing the <code class="computeroutput">Mutex</code> Type of a Signal (Advanced).</a></span></dt> 38<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.10">Linking against the Signals2 library</a></span></dt> 39</dl></div> 40<div class="section"> 41<div class="titlepage"><div><div><h3 class="title"> 42<a name="id-1.3.36.4.2"></a>How to Read this Tutorial</h3></div></div></div> 43<p>This tutorial is not meant to be read linearly. Its top-level 44structure roughly separates different concepts in the library 45(e.g., handling calling multiple slots, passing values to and from 46slots) and in each of these concepts the basic ideas are presented 47first and then more complex uses of the library are described 48later. Each of the sections is marked <span class="emphasis"><em>Beginner</em></span>, 49<span class="emphasis"><em>Intermediate</em></span>, or <span class="emphasis"><em>Advanced</em></span> to help guide the 50reader. The <span class="emphasis"><em>Beginner</em></span> sections include information that all 51library users should know; one can make good use of the Signals2 52library after having read only the <span class="emphasis"><em>Beginner</em></span> sections. The 53<span class="emphasis"><em>Intermediate</em></span> sections build on the <span class="emphasis"><em>Beginner</em></span> 54sections with slightly more complex uses of the library. Finally, 55the <span class="emphasis"><em>Advanced</em></span> sections detail very advanced uses of the 56Signals2 library, that often require a solid working knowledge of 57the <span class="emphasis"><em>Beginner</em></span> and <span class="emphasis"><em>Intermediate</em></span> topics; most users 58will not need to read the <span class="emphasis"><em>Advanced</em></span> sections.</p> 59</div> 60<div class="section"> 61<div class="titlepage"><div><div><h3 class="title"> 62<a name="id-1.3.36.4.3"></a>Hello, World! (Beginner)</h3></div></div></div> 63<p>The following example writes "Hello, World!" using signals and 64slots. First, we create a signal <code class="computeroutput">sig</code>, a signal that 65takes no arguments and has a void return value. Next, we connect 66the <code class="computeroutput">hello</code> function object to the signal using the 67<code class="computeroutput">connect</code> method. Finally, use the signal 68<code class="computeroutput">sig</code> like a function to call the slots, which in turns 69invokes <code class="computeroutput">HelloWorld::operator()</code> to print "Hello, 70World!".</p> 71<pre class="programlisting"><code class="computeroutput">struct HelloWorld 72{ 73 void operator()() const 74 { 75 std::cout << "Hello, World!" << std::endl; 76 } 77}; 78</code></pre> 79<pre class="programlisting"><code class="computeroutput"> // Signal with no arguments and a void return value 80 boost::signals2::signal<void ()> sig; 81 82 // Connect a HelloWorld slot 83 HelloWorld hello; 84 sig.connect(hello); 85 86 // Call all of the slots 87 sig(); 88</code></pre> 89</div> 90<div class="section"> 91<div class="titlepage"><div><div><h3 class="title"> 92<a name="id-1.3.36.4.4"></a>Calling Multiple Slots</h3></div></div></div> 93<div class="toc"><dl class="toc"> 94<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.4.2">Connecting Multiple Slots (Beginner)</a></span></dt> 95<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.4.3">Ordering Slot Call Groups (Intermediate)</a></span></dt> 96</dl></div> 97<div class="section"> 98<div class="titlepage"><div><div><h4 class="title"> 99<a name="id-1.3.36.4.4.2"></a>Connecting Multiple Slots (Beginner)</h4></div></div></div> 100<p>Calling a single slot from a signal isn't very interesting, so 101we can make the Hello, World program more interesting by splitting 102the work of printing "Hello, World!" into two completely separate 103slots. The first slot will print "Hello" and may look like 104this:</p> 105<pre class="programlisting"><code class="computeroutput">struct Hello 106{ 107 void operator()() const 108 { 109 std::cout << "Hello"; 110 } 111}; 112</code></pre> 113<p>The second slot will print ", World!" and a newline, to complete 114the program. The second slot may look like this:</p> 115<pre class="programlisting"><code class="computeroutput">struct World 116{ 117 void operator()() const 118 { 119 std::cout << ", World!" << std::endl; 120 } 121}; 122</code></pre> 123<p>Like in our previous example, we can create a signal 124<code class="computeroutput">sig</code> that takes no arguments and has a 125<code class="computeroutput">void</code> return value. This time, we connect both a 126<code class="computeroutput">hello</code> and a <code class="computeroutput">world</code> slot to the same 127signal, and when we call the signal both slots will be called.</p> 128<pre class="programlisting"><code class="computeroutput"> boost::signals2::signal<void ()> sig; 129 130 sig.connect(Hello()); 131 sig.connect(World()); 132 133 sig(); 134</code></pre> 135<p>By default, slots are pushed onto the back of the slot list, 136so the output of this program will be as expected:</p> 137<pre class="programlisting"> 138Hello, World! 139</pre> 140</div> 141<div class="section"> 142<div class="titlepage"><div><div><h4 class="title"> 143<a name="id-1.3.36.4.4.3"></a>Ordering Slot Call Groups (Intermediate)</h4></div></div></div> 144<p>Slots are free to have side effects, and that can mean that some 145slots will have to be called before others even if they are not connected in that order. The Boost.Signals2 146library allows slots to be placed into groups that are ordered in 147some way. For our Hello, World program, we want "Hello" to be 148printed before ", World!", so we put "Hello" into a group that must 149be executed before the group that ", World!" is in. To do this, we 150can supply an extra parameter at the beginning of the 151<code class="computeroutput">connect</code> call that specifies the group. Group values 152are, by default, <code class="computeroutput">int</code>s, and are ordered by the integer 153< relation. Here's how we construct Hello, World:</p> 154<pre class="programlisting"><code class="computeroutput"> boost::signals2::signal<void ()> sig; 155 156 sig.connect(1, World()); // connect with group 1 157 sig.connect(0, Hello()); // connect with group 0 158</code></pre> 159<p>Invoking the signal will correctly print "Hello, World!", because the 160<code class="computeroutput">Hello</code> object is in group 0, which precedes group 1 where 161the <code class="computeroutput">World</code> object resides. The group 162parameter is, in fact, optional. We omitted it in the first Hello, 163World example because it was unnecessary when all of the slots are 164independent. So what happens if we mix calls to connect that use the 165group parameter and those that don't? The "unnamed" slots (i.e., those 166that have been connected without specifying a group name) can be 167placed at the front or back of the slot list (by passing 168<code class="computeroutput">boost::signals2::at_front</code> or <code class="computeroutput">boost::signals2::at_back</code> 169as the last parameter to <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_1-bb">connect</a></code>, respectively), 170and default to the end of the list. When 171a group is specified, the final <code class="computeroutput">at_front</code> or <code class="computeroutput">at_back</code> 172parameter describes where the slot 173will be placed within the group ordering. Ungrouped slots connected with 174<code class="computeroutput">at_front</code> will always precede all grouped slots. Ungrouped 175slots connected with <code class="computeroutput">at_back</code> will always succeed all 176grouped slots. 177</p> 178<p> 179 If we add a new slot to our example like this: 180</p> 181<pre class="programlisting"><code class="computeroutput">struct GoodMorning 182{ 183 void operator()() const 184 { 185 std::cout << "... and good morning!" << std::endl; 186 } 187}; 188</code></pre> 189<pre class="programlisting"><code class="computeroutput"> // by default slots are connected at the end of the slot list 190 sig.connect(GoodMorning()); 191 192 // slots are invoked this order: 193 // 1) ungrouped slots connected with boost::signals2::at_front 194 // 2) grouped slots according to ordering of their groups 195 // 3) ungrouped slots connected with boost::signals2::at_back 196 sig(); 197</code></pre> 198<p>... we will get the result we wanted:</p> 199<pre class="programlisting"> 200Hello, World! 201... and good morning! 202</pre> 203</div> 204</div> 205<div class="section"> 206<div class="titlepage"><div><div><h3 class="title"> 207<a name="id-1.3.36.4.5"></a>Passing Values to and from Slots</h3></div></div></div> 208<div class="toc"><dl class="toc"> 209<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.5.2">Slot Arguments (Beginner)</a></span></dt> 210<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.5.3">Signal Return Values (Advanced)</a></span></dt> 211</dl></div> 212<div class="section"> 213<div class="titlepage"><div><div><h4 class="title"> 214<a name="id-1.3.36.4.5.2"></a>Slot Arguments (Beginner)</h4></div></div></div> 215<p>Signals can propagate arguments to each of the slots they call. 216For instance, a signal that propagates mouse motion events might 217want to pass along the new mouse coordinates and whether the mouse 218buttons are pressed.</p> 219<p>As an example, we'll create a signal that passes two 220<code class="computeroutput">float</code> arguments to its slots. Then we'll create a few 221slots that print the results of various arithmetic operations on 222these values.</p> 223<pre class="programlisting"><code class="computeroutput">void print_args(float x, float y) 224{ 225 std::cout << "The arguments are " << x << " and " << y << std::endl; 226} 227 228void print_sum(float x, float y) 229{ 230 std::cout << "The sum is " << x + y << std::endl; 231} 232 233void print_product(float x, float y) 234{ 235 std::cout << "The product is " << x * y << std::endl; 236} 237 238void print_difference(float x, float y) 239{ 240 std::cout << "The difference is " << x - y << std::endl; 241} 242 243void print_quotient(float x, float y) 244{ 245 std::cout << "The quotient is " << x / y << std::endl; 246} 247</code></pre> 248<pre class="programlisting"><code class="computeroutput"> boost::signals2::signal<void (float, float)> sig; 249 250 sig.connect(&print_args); 251 sig.connect(&print_sum); 252 sig.connect(&print_product); 253 sig.connect(&print_difference); 254 sig.connect(&print_quotient); 255 256 sig(5., 3.); 257</code></pre> 258<p>This program will print out the following:</p> 259<pre class="programlisting">The arguments are 5 and 3 260The sum is 8 261The product is 15 262The difference is 2 263The quotient is 1.66667</pre> 264<p>So any values that are given to <code class="computeroutput">sig</code> when it is 265called like a function are passed to each of the slots. We have to 266declare the types of these values up front when we create the 267signal. The type <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html" title="Class template signal">boost::signals2::signal</a><void (float, 268float)></code> means that the signal has a <code class="computeroutput">void</code> 269return value and takes two <code class="computeroutput">float</code> values. Any slot 270connected to <code class="computeroutput">sig</code> must therefore be able to take two 271<code class="computeroutput">float</code> values.</p> 272</div> 273<div class="section"> 274<div class="titlepage"><div><div><h4 class="title"> 275<a name="id-1.3.36.4.5.3"></a>Signal Return Values (Advanced)</h4></div></div></div> 276<p>Just as slots can receive arguments, they can also return 277values. These values can then be returned back to the caller of the 278signal through a <em class="firstterm">combiner</em>. The combiner is a mechanism 279that can take the results of calling slots (there may be no 280results or a hundred; we don't know until the program runs) and 281coalesces them into a single result to be returned to the caller. 282The single result is often a simple function of the results of the 283slot calls: the result of the last slot call, the maximum value 284returned by any slot, or a container of all of the results are some 285possibilities.</p> 286<p>We can modify our previous arithmetic operations example 287slightly so that the slots all return the results of computing the 288product, quotient, sum, or difference. Then the signal itself can 289return a value based on these results to be printed:</p> 290<pre class="programlisting"><code class="computeroutput">float product(float x, float y) { return x * y; } 291float quotient(float x, float y) { return x / y; } 292float sum(float x, float y) { return x + y; } 293float difference(float x, float y) { return x - y; } 294</code></pre> 295<pre class="programlisting">boost::signals2::signal<float (float, float)> sig;</pre> 296<pre class="programlisting"><code class="computeroutput"> sig.connect(&product); 297 sig.connect(&quotient); 298 sig.connect(&sum); 299 sig.connect(&difference); 300 301 // The default combiner returns a boost::optional containing the return 302 // value of the last slot in the slot list, in this case the 303 // difference function. 304 std::cout << *sig(5, 3) << std::endl; 305</code></pre> 306<p>This example program will output <code class="computeroutput">2</code>. This is because the 307default behavior of a signal that has a return type 308(<code class="computeroutput">float</code>, the first template argument given to the 309<code class="computeroutput"><a class="link" href="../boost/signals2/signal.html" title="Class template signal">boost::signals2::signal</a></code> class template) is to call all slots and 310then return a <code class="computeroutput">boost::optional</code> containing 311the result returned by the last slot called. This 312behavior is admittedly silly for this example, because slots have 313no side effects and the result is the last slot connected.</p> 314<p>A more interesting signal result would be the maximum of the 315values returned by any slot. To do this, we create a custom 316combiner that looks like this:</p> 317<pre class="programlisting"><code class="computeroutput">// combiner which returns the maximum value returned by all slots 318template<typename T> 319struct maximum 320{ 321 typedef T result_type; 322 323 template<typename InputIterator> 324 T operator()(InputIterator first, InputIterator last) const 325 { 326 // If there are no slots to call, just return the 327 // default-constructed value 328 if(first == last ) return T(); 329 T max_value = *first++; 330 while (first != last) { 331 if (max_value < *first) 332 max_value = *first; 333 ++first; 334 } 335 336 return max_value; 337 } 338}; 339</code></pre> 340<p>The <code class="computeroutput">maximum</code> class template acts as a function 341object. Its result type is given by its template parameter, and 342this is the type it expects to be computing the maximum based on 343(e.g., <code class="computeroutput">maximum<float></code> would find the maximum 344<code class="computeroutput">float</code> in a sequence of <code class="computeroutput">float</code>s). When a 345<code class="computeroutput">maximum</code> object is invoked, it is given an input 346iterator sequence <code class="computeroutput">[first, last)</code> that includes the 347results of calling all of the slots. <code class="computeroutput">maximum</code> uses this 348input iterator sequence to calculate the maximum element, and 349returns that maximum value.</p> 350<p>We actually use this new function object type by installing it 351as a combiner for our signal. The combiner template argument 352follows the signal's calling signature:</p> 353<pre class="programlisting"> 354<code class="computeroutput"><a class="link" href="../boost/signals2/signal.html" title="Class template signal">boost::signals2::signal</a></code><float (float x, float y), 355 maximum<float> > sig; 356</pre> 357<p>Now we can connect slots that perform arithmetic functions and 358use the signal:</p> 359<pre class="programlisting"><code class="computeroutput"> sig.connect(&product); 360 sig.connect(&quotient); 361 sig.connect(&sum); 362 sig.connect(&difference); 363 364 // Outputs the maximum value returned by the connected slots, in this case 365 // 15 from the product function. 366 std::cout << "maximum: " << sig(5, 3) << std::endl; 367</code></pre> 368<p>The output of this program will be <code class="computeroutput">15</code>, because 369regardless of the order in which the slots are connected, the product 370of 5 and 3 will be larger than the quotient, sum, or 371difference.</p> 372<p>In other cases we might want to return all of the values 373computed by the slots together, in one large data structure. This 374is easily done with a different combiner:</p> 375<pre class="programlisting"><code class="computeroutput">// aggregate_values is a combiner which places all the values returned 376// from slots into a container 377template<typename Container> 378struct aggregate_values 379{ 380 typedef Container result_type; 381 382 template<typename InputIterator> 383 Container operator()(InputIterator first, InputIterator last) const 384 { 385 Container values; 386 387 while(first != last) { 388 values.push_back(*first); 389 ++first; 390 } 391 return values; 392 } 393}; 394</code></pre> 395<p> 396Again, we can create a signal with this new combiner: 397</p> 398<pre class="programlisting"> 399<code class="computeroutput"><a class="link" href="../boost/signals2/signal.html" title="Class template signal">boost::signals2::signal</a></code><float (float, float), 400 aggregate_values<std::vector<float> > > sig;</pre> 401<pre class="programlisting"><code class="computeroutput"> sig.connect(&quotient); 402 sig.connect(&product); 403 sig.connect(&sum); 404 sig.connect(&difference); 405 406 std::vector<float> results = sig(5, 3); 407 std::cout << "aggregate values: "; 408 std::copy(results.begin(), results.end(), 409 std::ostream_iterator<float>(std::cout, " ")); 410 std::cout << "\n"; 411</code></pre> 412<p>The output of this program will contain 15, 8, 1.6667, and 2. It 413is interesting here that 414the first template argument for the <code class="computeroutput">signal</code> class, 415<code class="computeroutput">float</code>, is not actually the return type of the signal. 416Instead, it is the return type used by the connected slots and will 417also be the <code class="computeroutput">value_type</code> of the input iterators passed 418to the combiner. The combiner itself is a function object and its 419<code class="computeroutput">result_type</code> member type becomes the return type of the 420signal.</p> 421<p>The input iterators passed to the combiner transform dereference 422operations into slot calls. Combiners therefore have the option to 423invoke only some slots until some particular criterion is met. For 424instance, in a distributed computing system, the combiner may ask 425each remote system whether it will handle the request. Only one 426remote system needs to handle a particular request, so after a 427remote system accepts the work we do not want to ask any other 428remote systems to perform the same task. Such a combiner need only 429check the value returned when dereferencing the iterator, and 430return when the value is acceptable. The following combiner returns 431the first non-NULL pointer to a <code class="computeroutput">FulfilledRequest</code> data 432structure, without asking any later slots to fulfill the 433request:</p> 434<pre class="programlisting"> 435struct DistributeRequest { 436 typedef FulfilledRequest* result_type; 437 438 template<typename InputIterator> 439 result_type operator()(InputIterator first, InputIterator last) const 440 { 441 while (first != last) { 442 if (result_type fulfilled = *first) 443 return fulfilled; 444 ++first; 445 } 446 return 0; 447 } 448}; 449</pre> 450</div> 451</div> 452<div class="section"> 453<div class="titlepage"><div><div><h3 class="title"> 454<a name="id-1.3.36.4.6"></a>Connection Management</h3></div></div></div> 455<div class="toc"><dl class="toc"> 456<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.6.2">Disconnecting Slots (Beginner)</a></span></dt> 457<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.6.3">Blocking Slots (Beginner)</a></span></dt> 458<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.6.4">Scoped Connections (Intermediate)</a></span></dt> 459<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.6.5">Disconnecting Equivalent Slots (Intermediate)</a></span></dt> 460<dt><span class="section"><a href="tutorial.html#signals2.tutorial.connection-management">Automatic Connection Management (Intermediate)</a></span></dt> 461<dt><span class="section"><a href="tutorial.html#signals2.tutorial.deconstruct">Postconstructors and Predestructors (Advanced)</a></span></dt> 462<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.6.9">When Can Disconnections Occur? (Intermediate)</a></span></dt> 463<dt><span class="section"><a href="tutorial.html#id-1.3.36.4.6.10">Passing Slots (Intermediate)</a></span></dt> 464</dl></div> 465<div class="section"> 466<div class="titlepage"><div><div><h4 class="title"> 467<a name="id-1.3.36.4.6.2"></a>Disconnecting Slots (Beginner)</h4></div></div></div> 468<p>Slots aren't expected to exist indefinitely after they are 469connected. Often slots are only used to receive a few events and 470are then disconnected, and the programmer needs control to decide 471when a slot should no longer be connected.</p> 472<p>The entry point for managing connections explicitly is the 473<code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">boost::signals2::connection</a></code> class. The 474<code class="computeroutput">connection</code> class uniquely represents the connection 475between a particular signal and a particular slot. The 476<code class="computeroutput"><a class="link" href="../boost/signals2/connection.html#id-1_3_36_6_2_1_1_1_8_2-bb">connected</a>()</code> method checks if the signal and slot are 477still connected, and the <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html#id-1_3_36_6_2_1_1_1_8_1-bb">disconnect()</a></code> method 478disconnects the signal and slot if they are connected before it is 479called. Each call to the signal's <code class="computeroutput">connect()</code> method 480returns a connection object, which can be used to determine if the 481connection still exists or to disconnect the signal and slot.</p> 482<pre class="programlisting"><code class="computeroutput"> boost::signals2::connection c = sig.connect(HelloWorld()); 483 std::cout << "c is connected\n"; 484 sig(); // Prints "Hello, World!" 485 486 c.disconnect(); // Disconnect the HelloWorld object 487 std::cout << "c is disconnected\n"; 488 sig(); // Does nothing: there are no connected slots 489</code></pre> 490</div> 491<div class="section"> 492<div class="titlepage"><div><div><h4 class="title"> 493<a name="id-1.3.36.4.6.3"></a>Blocking Slots (Beginner)</h4></div></div></div> 494<p>Slots can be temporarily "blocked", meaning that they will be 495ignored when the signal is invoked but have not been permanently disconnected. 496This is typically used to prevent infinite recursion in cases where 497otherwise running a slot would cause the signal it is connected to to be 498invoked again. A 499<code class="computeroutput"><a class="link" href="../boost/signals2/shared_connection_block.html" title="Class shared_connection_block">boost::signals2::shared_connection_block</a></code> object will 500temporarily block a slot. The connection is unblocked by either 501destroying or calling 502<code class="computeroutput"><a class="link" href="../boost/signals2/shared_connection_block.html#id-1_3_36_6_8_4_1_1_7_1-bb">unblock</a></code> 503on all the 504<code class="computeroutput">shared_connection_block</code> objects that reference the connection. 505Here is an example of 506blocking/unblocking slots:</p> 507<pre class="programlisting"><code class="computeroutput"> boost::signals2::connection c = sig.connect(HelloWorld()); 508 std::cout << "c is not blocked.\n"; 509 sig(); // Prints "Hello, World!" 510 511 { 512 boost::signals2::shared_connection_block block(c); // block the slot 513 std::cout << "c is blocked.\n"; 514 sig(); // No output: the slot is blocked 515 } // shared_connection_block going out of scope unblocks the slot 516 std::cout << "c is not blocked.\n"; 517 sig(); // Prints "Hello, World!"} 518</code></pre> 519</div> 520<div class="section"> 521<div class="titlepage"><div><div><h4 class="title"> 522<a name="id-1.3.36.4.6.4"></a>Scoped Connections (Intermediate)</h4></div></div></div> 523<p>The <code class="computeroutput"><a class="link" href="../boost/signals2/scoped_connection.html" title="Class scoped_connection">boost::signals2::scoped_connection</a></code> class 524references a signal/slot connection that will be disconnected when 525the <code class="computeroutput">scoped_connection</code> class goes out of scope. This 526ability is useful when a connection need only be temporary, 527e.g.,</p> 528<pre class="programlisting"><code class="computeroutput"> { 529 boost::signals2::scoped_connection c(sig.connect(ShortLived())); 530 sig(); // will call ShortLived function object 531 } // scoped_connection goes out of scope and disconnects 532 533 sig(); // ShortLived function object no longer connected to sig 534</code></pre> 535<p> 536 Note, attempts to initialize a scoped_connection with the assignment syntax 537 will fail due to it being noncopyable. Either the explicit initialization syntax 538 or default construction followed by assignment from a <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> 539 will work: 540</p> 541<pre class="programlisting"> 542// doesn't compile due to compiler attempting to copy a temporary scoped_connection object 543// boost::signals2::scoped_connection c0 = sig.<code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_1-bb">connect</a></code>(ShortLived()); 544 545// okay 546boost::signals2::scoped_connection c1(sig.<code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_1-bb">connect</a></code>(ShortLived())); 547 548// also okay 549boost::signals2::scoped_connection c2; 550c2 = sig.<code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_1-bb">connect</a></code>(ShortLived()); 551</pre> 552</div> 553<div class="section"> 554<div class="titlepage"><div><div><h4 class="title"> 555<a name="id-1.3.36.4.6.5"></a>Disconnecting Equivalent Slots (Intermediate)</h4></div></div></div> 556<p>One can disconnect slots that are equivalent to a given function 557object using a form of the 558<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> method, so long as 559the type of the function object has an accessible <code class="computeroutput">==</code> 560operator. For instance: 561 562</p> 563<pre class="programlisting"><code class="computeroutput">void foo() { std::cout << "foo"; } 564void bar() { std::cout << "bar\n"; } 565</code></pre> 566<pre class="programlisting"><code class="computeroutput"><a class="link" href="../boost/signals2/signal.html" title="Class template signal">boost::signals2::signal</a></code><void ()> sig;</pre> 567</div> 568<pre class="programlisting"><code class="computeroutput"> sig.connect(&foo); 569 sig.connect(&bar); 570 sig(); 571 572 // disconnects foo, but not bar 573 sig.disconnect(&foo); 574 sig(); 575</code></pre> 576<div class="section"> 577<div class="titlepage"><div><div><h4 class="title"> 578<a name="signals2.tutorial.connection-management"></a>Automatic Connection Management (Intermediate)</h4></div></div></div> 579<p>Boost.Signals2 can automatically track the lifetime of objects 580involved in signal/slot connections, including automatic 581disconnection of slots when objects involved in the slot call are 582destroyed. For instance, consider a simple news delivery service, 583where clients connect to a news provider that then sends news to 584all connected clients as information arrives. The news delivery 585service may be constructed like this: </p> 586<pre class="programlisting"> 587class NewsItem { /* ... */ }; 588 589typedef boost::signals2::signal<void (const NewsItem&)> signal_type; 590signal_type deliverNews; 591</pre> 592<p>Clients that wish to receive news updates need only connect a 593function object that can receive news items to the 594<code class="computeroutput">deliverNews</code> signal. For instance, we may have a 595special message area in our application specifically for news, 596e.g.,:</p> 597<pre class="programlisting"> 598struct NewsMessageArea : public MessageArea 599{ 600public: 601 // ... 602 603 void displayNews(const NewsItem& news) const 604 { 605 messageText = news.text(); 606 update(); 607 } 608}; 609 610// ... 611NewsMessageArea *newsMessageArea = new NewsMessageArea(/* ... */); 612// ... 613deliverNews.<code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_1-bb">connect</a></code>(boost::bind(&NewsMessageArea::displayNews, 614 newsMessageArea, _1)); 615</pre> 616<p>However, what if the user closes the news message area, 617destroying the <code class="computeroutput">newsMessageArea</code> object that 618<code class="computeroutput">deliverNews</code> knows about? Most likely, a segmentation 619fault will occur. However, with Boost.Signals2 one may track any object 620which is managed by a shared_ptr, by using 621<code class="computeroutput"><a class="link" href="../boost/signals2/slot.html#id-1_3_36_6_12_5_1_1_17_1-bb">slot::track</a></code>. A slot will automatically 622disconnect when any of its tracked objects expire. In 623addition, Boost.Signals2 will ensure that no tracked object expires 624while the slot it is associated with is in mid-execution. It does so by creating 625temporary shared_ptr copies of the slot's tracked objects before executing it. 626To track <code class="computeroutput">NewsMessageArea</code>, we use a shared_ptr to manage 627its lifetime, and pass the shared_ptr to the slot via its 628<code class="computeroutput"><a class="link" href="../boost/signals2/slot.html#id-1_3_36_6_12_5_1_1_17_1-bb">slot::track</a></code> 629method before connecting it, 630e.g.:</p> 631<pre class="programlisting"> 632// ... 633boost::shared_ptr<NewsMessageArea> newsMessageArea(new NewsMessageArea(/* ... */)); 634// ... 635deliverNews.<code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_1-bb">connect</a></code>(signal_type::slot_type(&NewsMessageArea::displayNews, 636 newsMessageArea.get(), _1).track(newsMessageArea)); 637</pre> 638<p> 639 Note there is no explicit call to bind() needed in the above example. If the 640 <code class="computeroutput"><a class="link" href="../boost/signals2/slot.html" title="Class template slot">signals2::slot</a></code> constructor is passed more than one 641 argument, it will automatically pass all the arguments to <code class="computeroutput">bind</code> and use the 642 returned function object. 643</p> 644<p>Also note, we pass an ordinary pointer as the 645 second argument to the slot constructor, using <code class="computeroutput">newsMessageArea.get()</code> 646 instead of passing the <code class="computeroutput">shared_ptr</code> itself. If we had passed the 647 <code class="computeroutput">newsMessageArea</code> itself, a copy of the <code class="computeroutput">shared_ptr</code> would 648 have been bound into the slot function, preventing the <code class="computeroutput">shared_ptr</code> 649 from expiring. However, the use of 650 <code class="computeroutput"><a class="link" href="../boost/signals2/slot.html#id-1_3_36_6_12_5_1_1_17_1-bb">slot::track</a></code> 651 implies we wish to allow the tracked object to expire, and automatically 652 disconnect the connection when this occurs. 653</p> 654<p> 655 <code class="computeroutput">shared_ptr</code> classes other than <code class="computeroutput">boost::shared_ptr</code> 656 (such as <code class="computeroutput">std::shared_ptr</code>) may also be tracked for connection management 657 purposes. They are supported by the <code class="computeroutput"><a class="link" href="../boost/signals2/slot.html#id-1_3_36_6_12_5_1_1_17_2-bb">slot::track_foreign</a></code> method. 658</p> 659</div> 660<div class="section"> 661<div class="titlepage"><div><div><h4 class="title"> 662<a name="signals2.tutorial.deconstruct"></a>Postconstructors and Predestructors (Advanced)</h4></div></div></div> 663<p>One limitation of using <code class="computeroutput">shared_ptr</code> for tracking is that 664 an object cannot setup tracking of itself in its constructor. However, it is 665 possible to set up tracking in a post-constructor which is called after the 666 object has been created and passed to a <code class="computeroutput">shared_ptr</code>. 667 The Boost.Signals2 668 library provides support for post-constructors and pre-destructors 669 via the <code class="computeroutput"><a class="link" href="../boost/signals2/deconstruct.html" title="Function deconstruct">deconstruct()</a></code> factory function. 670 </p> 671<p> 672 For most cases, the simplest and most robust way to setup postconstructors 673 for a class is to define an associated <code class="computeroutput">adl_postconstruct</code> function 674 which can be found by <code class="computeroutput"><a class="link" href="../boost/signals2/deconstruct.html" title="Function deconstruct">deconstruct()</a></code>, 675 make the class' constructors private, and give <code class="computeroutput"><a class="link" href="../boost/signals2/deconstruct.html" title="Function deconstruct">deconstruct</a></code> 676 access to the private constructors by declaring <code class="computeroutput"><a class="link" href="../boost/signals2/deconstruct_access.html" title="Class deconstruct_access">deconstruct_access</a></code> 677 a friend. This will ensure that objects of the class may only be created 678 through the <code class="computeroutput"><a class="link" href="../boost/signals2/deconstruct.html" title="Function deconstruct">deconstruct()</a></code> function, and their 679 associated <code class="computeroutput">adl_postconstruct()</code> function will always be called. 680 </p> 681<p>The <a class="link" href="examples.html#signals2.examples.deconstruct" title="Postconstructors and Predestructors with deconstruct()">examples</a> section 682 contains several examples of defining classes with postconstructors and 683 predestructors, and creating objects of these classes using 684 <code class="computeroutput"><a class="link" href="../boost/signals2/deconstruct.html" title="Function deconstruct">deconstruct()</a></code> 685 </p> 686<p> 687 Be aware that the postconstructor/predestructor support in Boost.Signals2 688 is in no way essential to the use of the library. The use of 689 <code class="computeroutput"><a class="link" href="../boost/signals2/deconstruct.html" title="Function deconstruct">deconstruct</a></code> 690 is purely optional. One alternative is to 691 define static factory functions for your classes. The 692 factory function can create an object, pass ownership of the object to 693 a <code class="computeroutput">shared_ptr</code>, setup tracking for the object, 694 then return the <code class="computeroutput">shared_ptr</code>. 695 </p> 696</div> 697<div class="section"> 698<div class="titlepage"><div><div><h4 class="title"> 699<a name="id-1.3.36.4.6.9"></a>When Can Disconnections Occur? (Intermediate)</h4></div></div></div> 700<p>Signal/slot disconnections occur when any of these conditions 701occur:</p> 702<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "> 703<li class="listitem"><p>The connection is explicitly disconnected via the connection's 704<code class="computeroutput">disconnect</code> method directly, or indirectly via the 705signal's <code class="computeroutput">disconnect</code> method, or 706<code class="computeroutput">scoped_connection</code>'s destructor.</p></li> 707<li class="listitem"><p>An object tracked by the slot is 708destroyed.</p></li> 709<li class="listitem"><p>The signal is destroyed.</p></li> 710</ul></div> 711<p>These events can occur at any time without disrupting a signal's 712calling sequence. If a signal/slot connection is disconnected at 713any time during a signal's calling sequence, the calling sequence 714will still continue but will not invoke the disconnected slot. 715Additionally, a signal may be destroyed while it is in a calling 716sequence, in which case it will complete its slot call sequence 717but may not be accessed directly.</p> 718<p>Signals may be invoked recursively (e.g., a signal A calls a 719slot B that invokes signal A...). The disconnection behavior does 720not change in the recursive case, except that the slot calling 721sequence includes slot calls for all nested invocations of the 722signal.</p> 723<p> 724 Note, even after a connection is disconnected, its's associated slot 725 may still be in the process of executing. In other words, disconnection 726 does not block waiting for the connection's associated slot to complete execution. 727 This situation may occur in a multi-threaded environment if the 728 disconnection occurs concurrently with signal invocation, 729 or in a single-threaded environment if a slot disconnects itself. 730</p> 731</div> 732<div class="section"> 733<div class="titlepage"><div><div><h4 class="title"> 734<a name="id-1.3.36.4.6.10"></a>Passing Slots (Intermediate)</h4></div></div></div> 735<p>Slots in the Boost.Signals2 library are created from arbitrary 736function objects, and therefore have no fixed type. However, it is 737commonplace to require that slots be passed through interfaces that 738cannot be templates. Slots can be passed via the 739<code class="computeroutput">slot_type</code> for each particular signal type and any 740function object compatible with the signature of the signal can be 741passed to a <code class="computeroutput">slot_type</code> parameter. For instance:</p> 742<pre class="programlisting"><code class="computeroutput">// a pretend GUI button 743class Button 744{ 745 typedef boost::signals2::signal<void (int x, int y)> OnClick; 746public: 747 typedef OnClick::slot_type OnClickSlotType; 748 // forward slots through Button interface to its private signal 749 boost::signals2::connection doOnClick(const OnClickSlotType & slot); 750 751 // simulate user clicking on GUI button at coordinates 52, 38 752 void simulateClick(); 753private: 754 OnClick onClick; 755}; 756 757boost::signals2::connection Button::doOnClick(const OnClickSlotType & slot) 758{ 759 return onClick.connect(slot); 760} 761 762void Button::simulateClick() 763{ 764 onClick(52, 38); 765} 766 767void printCoordinates(long x, long y) 768{ 769 std::cout << "(" << x << ", " << y << ")\n"; 770} 771</code></pre> 772<pre class="programlisting"> 773<code class="computeroutput"> Button button; 774 button.doOnClick(&printCoordinates); 775 button.simulateClick(); 776</code></pre> 777<p>The <code class="computeroutput">doOnClick</code> method is now functionally equivalent 778to the <code class="computeroutput">connect</code> method of the <code class="computeroutput">onClick</code> 779signal, but the details of the <code class="computeroutput">doOnClick</code> method can be 780hidden in an implementation detail file.</p> 781</div> 782</div> 783<div class="section"> 784<div class="titlepage"><div><div><h3 class="title"> 785<a name="signals2.tutorial.document-view"></a>Example: Document-View</h3></div></div></div> 786<p>Signals can be used to implement flexible Document-View 787 architectures. The document will contain a signal to which each of 788 the views can connect. The following <code class="computeroutput">Document</code> class 789 defines a simple text document that supports mulitple views. Note 790 that it stores a single signal to which all of the views will be 791 connected.</p> 792<pre class="programlisting"><code class="computeroutput">class Document 793{ 794public: 795 typedef boost::signals2::signal<void ()> signal_t; 796 797public: 798 Document() 799 {} 800 801 /* Connect a slot to the signal which will be emitted whenever 802 text is appended to the document. */ 803 boost::signals2::connection connect(const signal_t::slot_type &subscriber) 804 { 805 return m_sig.connect(subscriber); 806 } 807 808 void append(const char* s) 809 { 810 m_text += s; 811 m_sig(); 812 } 813 814 const std::string& getText() const 815 { 816 return m_text; 817 } 818 819private: 820 signal_t m_sig; 821 std::string m_text; 822}; 823</code></pre> 824<p> 825 Next, we can begin to define views. The 826 following <code class="computeroutput">TextView</code> class provides a simple view of the 827 document text. 828 </p> 829<pre class="programlisting"><code class="computeroutput">class TextView 830{ 831public: 832 TextView(Document& doc): m_document(doc) 833 { 834 m_connection = m_document.connect(boost::bind(&TextView::refresh, this)); 835 } 836 837 ~TextView() 838 { 839 m_connection.disconnect(); 840 } 841 842 void refresh() const 843 { 844 std::cout << "TextView: " << m_document.getText() << std::endl; 845 } 846private: 847 Document& m_document; 848 boost::signals2::connection m_connection; 849}; 850</code></pre> 851<p>Alternatively, we can provide a view of the document 852 translated into hex values using the <code class="computeroutput">HexView</code> 853 view:</p> 854<pre class="programlisting"><code class="computeroutput">class HexView 855{ 856public: 857 HexView(Document& doc): m_document(doc) 858 { 859 m_connection = m_document.connect(boost::bind(&HexView::refresh, this)); 860 } 861 862 ~HexView() 863 { 864 m_connection.disconnect(); 865 } 866 867 void refresh() const 868 { 869 const std::string& s = m_document.getText(); 870 871 std::cout << "HexView:"; 872 873 for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) 874 std::cout << ' ' << std::hex << static_cast<int>(*it); 875 876 std::cout << std::endl; 877 } 878private: 879 Document& m_document; 880 boost::signals2::connection m_connection; 881}; 882</code></pre> 883<p> 884 To tie the example together, here is a 885 simple <code class="computeroutput">main</code> function that sets up two views and then 886 modifies the document: 887 </p> 888<pre class="programlisting"><code class="computeroutput">int main(int argc, char* argv[]) 889{ 890 Document doc; 891 TextView v1(doc); 892 HexView v2(doc); 893 894 doc.append(argc == 2 ? argv[1] : "Hello world!"); 895 return 0; 896} 897</code></pre> 898<p>The complete example source, contributed by Keith MacDonald, 899 is available in the <a class="link" href="examples.html#signals2.examples.document-view" title="Document-View">examples</a> section. 900 We also provide variations on the program which employ automatic connection management 901 to disconnect views on their destruction. 902 </p> 903</div> 904<div class="section"> 905<div class="titlepage"><div><div><h3 class="title"> 906<a name="signals2.tutorial.extended-slot-type"></a>Giving a Slot Access to its Connection (Advanced)</h3></div></div></div> 907<p> 908 You may encounter situations where you wish to disconnect or block a slot's 909 connection from within the slot itself. For example, suppose you have a group 910 of asynchronous tasks, each of which emits a signal when it completes. 911 You wish to connect a slot to all the tasks to retrieve their results as 912 each completes. Once a 913 given task completes and the slot is run, the slot no longer needs to be 914 connected to the completed task. 915 Therefore, you may wish to clean up old connections by having the slot 916 disconnect its invoking connection when it runs. 917 </p> 918<p> 919 For a slot to disconnect (or block) its invoking connection, it must have 920 access to a <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> object which references 921 the invoking signal-slot connection. The difficulty is, 922 the <code class="computeroutput">connection</code> object is returned by the 923 <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_1-bb">signal::connect</a></code> 924 method, and therefore is not available until after the slot is 925 already connected to the signal. This can be particularly troublesome 926 in a multi-threaded environment where the signal may be invoked 927 concurrently by a different thread while the slot is being connected. 928 </p> 929<p> 930 Therefore, the signal classes provide 931 <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_2-bb">signal::connect_extended</a></code> 932 methods, which allow slots which take an extra argument to be connected to a signal. 933 The extra argument is a <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> object which refers 934 to the signal-slot connection currently invoking the slot. 935 <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_2-bb">signal::connect_extended</a></code> 936 uses slots of the type given by the 937 <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#boost.signals2.signal.extended_slot_type">signal::extended_slot_type</a></code> 938 typedef. 939 </p> 940<p> 941 The examples section includes an 942 <a class="link" href="examples.html#signals2.examples.tutorial.extended_slot" title="extended_slot">extended_slot</a> 943 program which demonstrates the syntax for using 944 <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_36_6_9_3_1_2_24_2-bb">signal::connect_extended</a></code>. 945 </p> 946</div> 947<div class="section"> 948<div class="titlepage"><div><div><h3 class="title"> 949<a name="signals2.tutorial.signal-mutex-template-parameter"></a>Changing the <code class="computeroutput">Mutex</code> Type of a Signal (Advanced).</h3></div></div></div> 950<p> 951 For most cases the default type of <code class="computeroutput"><a class="link" href="../boost/signals2/mutex.html" title="Class mutex">boost::signals2::mutex</a></code> for 952 a <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html" title="Class template signal">signals2::signal</a></code>'s <code class="computeroutput">Mutex</code> template type parameter should 953 be fine. If you wish to use an alternate mutex type, it must be default-constructible 954 and fulfill the <code class="computeroutput">Lockable</code> concept defined by the Boost.Thread library. 955 That is, it must have <code class="computeroutput">lock()</code> and <code class="computeroutput">unlock()</code> methods 956 (the <code class="computeroutput">Lockable</code> concept also includes a <code class="computeroutput">try_lock()</code> method 957 but this library does not require try locking). 958 </p> 959<p> 960 The Boost.Signals2 library provides one alternate mutex class for use with <code class="computeroutput">signal</code>: 961 <code class="computeroutput"><a class="link" href="../boost/signals2/dummy_mutex.html" title="Class dummy_mutex">boost::signals2::dummy_mutex</a></code>. This is a fake mutex for 962 use in single-threaded programs, where locking a real mutex would be useless 963 overhead. Other mutex types you could use with <code class="computeroutput">signal</code> include 964 <code class="computeroutput">boost::mutex</code>, or the <code class="computeroutput">std::mutex</code> from 965 C++11. 966 </p> 967<p> 968 Changing a signal's <code class="computeroutput">Mutex</code> template type parameter can be tedious, due to 969 the large number of template parameters which precede it. The 970 <code class="computeroutput"><a class="link" href="../boost/signals2/signal_type.html" title="Class template signal_type">signal_type</a></code> metafunction is particularly useful in this case, 971 since it enables named template type parameters for the <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html" title="Class template signal">signals2::signal</a></code> 972 class. For example, to declare a signal which takes an <code class="computeroutput">int</code> as 973 an argument and uses a <code class="computeroutput"><a class="link" href="../boost/signals2/dummy_mutex.html" title="Class dummy_mutex">boost::signals2::dummy_mutex</a></code> 974 for its <code class="computeroutput">Mutex</code> types, you could write: 975 </p> 976<pre class="programlisting">namespace bs2 = boost::signals2; 977using namespace bs2::keywords; 978bs2::signal_type<void (int), mutex_type<bs2::dummy_mutex> >::type sig; 979</pre> 980</div> 981<div class="section"> 982<div class="titlepage"><div><div><h3 class="title"> 983<a name="id-1.3.36.4.10"></a>Linking against the Signals2 library</h3></div></div></div> 984<p>Unlike the original Boost.Signals library, Boost.Signals2 is currently header-only. 985 </p> 986</div> 987</div> 988<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> 989<td align="left"><p><small>Last revised: June 12, 2007 at 14:01:23 -0400</small></p></td> 990<td align="right"><div class="copyright-footer">Copyright © 2001-2004 Douglas Gregor<br>Copyright © 2007-2009 Frank Mori Hess<p>Distributed under the Boost 991 Software License, Version 1.0. (See accompanying file 992 <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> 993</div></td> 994</tr></table> 995<hr> 996<div class="spirit-nav"> 997<a accesskey="p" href="../signals2.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="examples.html"><img src="../../../doc/src/images/next.png" alt="Next"></a> 998</div> 999</body> 1000</html> 1001