]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/signals2/doc/tutorial.xml
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / signals2 / doc / tutorial.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
3 "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
4 <!--
5 Copyright Douglas Gregor 2001-2004
6 Copyright Frank Mori Hess 2007-2009
7
8 Distributed under the Boost Software License, Version 1.0. (See accompanying
9 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 -->
11 <section last-revision="$Date: 2007-06-12 14:01:23 -0400 (Tue, 12 Jun 2007) $" id="signals2.tutorial">
12 <title>Tutorial</title>
13
14 <using-namespace name="boost::signals2"/>
15 <using-namespace name="boost"/>
16 <using-class name="boost::signals2::signal"/>
17 <using-class name="boost::signals2::slot"/>
18
19 <section>
20 <title>How to Read this Tutorial</title>
21 <para>This tutorial is not meant to be read linearly. Its top-level
22 structure roughly separates different concepts in the library
23 (e.g., handling calling multiple slots, passing values to and from
24 slots) and in each of these concepts the basic ideas are presented
25 first and then more complex uses of the library are described
26 later. Each of the sections is marked <emphasis>Beginner</emphasis>,
27 <emphasis>Intermediate</emphasis>, or <emphasis>Advanced</emphasis> to help guide the
28 reader. The <emphasis>Beginner</emphasis> sections include information that all
29 library users should know; one can make good use of the Signals2
30 library after having read only the <emphasis>Beginner</emphasis> sections. The
31 <emphasis>Intermediate</emphasis> sections build on the <emphasis>Beginner</emphasis>
32 sections with slightly more complex uses of the library. Finally,
33 the <emphasis>Advanced</emphasis> sections detail very advanced uses of the
34 Signals2 library, that often require a solid working knowledge of
35 the <emphasis>Beginner</emphasis> and <emphasis>Intermediate</emphasis> topics; most users
36 will not need to read the <emphasis>Advanced</emphasis> sections.</para>
37 </section>
38
39 <section><title>Hello, World! (Beginner)</title>
40 <para>The following example writes "Hello, World!" using signals and
41 slots. First, we create a signal <code>sig</code>, a signal that
42 takes no arguments and has a void return value. Next, we connect
43 the <code>hello</code> function object to the signal using the
44 <code>connect</code> method. Finally, use the signal
45 <code>sig</code> like a function to call the slots, which in turns
46 invokes <code>HelloWorld::operator()</code> to print "Hello,
47 World!".</para>
48 <programlisting><xi:include href="hello_world_def_code_snippet.xml"
49 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
50 <programlisting><xi:include href="hello_world_single_code_snippet.xml"
51 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
52 </section>
53
54 <section><title>Calling Multiple Slots</title>
55 <section><title>Connecting Multiple Slots (Beginner)</title>
56 <para>Calling a single slot from a signal isn't very interesting, so
57 we can make the Hello, World program more interesting by splitting
58 the work of printing "Hello, World!" into two completely separate
59 slots. The first slot will print "Hello" and may look like
60 this:</para>
61 <programlisting><xi:include href="hello_def_code_snippet.xml"
62 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
63 <para>The second slot will print ", World!" and a newline, to complete
64 the program. The second slot may look like this:</para>
65 <programlisting><xi:include href="world_def_code_snippet.xml"
66 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
67 <para>Like in our previous example, we can create a signal
68 <code>sig</code> that takes no arguments and has a
69 <code>void</code> return value. This time, we connect both a
70 <code>hello</code> and a <code>world</code> slot to the same
71 signal, and when we call the signal both slots will be called.</para>
72 <programlisting><xi:include href="hello_world_multi_code_snippet.xml"
73 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
74 <para>By default, slots are pushed onto the back of the slot list,
75 so the output of this program will be as expected:</para>
76 <programlisting>
77 Hello, World!
78 </programlisting>
79 </section>
80
81 <section><title>Ordering Slot Call Groups (Intermediate)</title>
82 <para>Slots are free to have side effects, and that can mean that some
83 slots will have to be called before others even if they are not connected in that order. The Boost.Signals2
84 library allows slots to be placed into groups that are ordered in
85 some way. For our Hello, World program, we want "Hello" to be
86 printed before ", World!", so we put "Hello" into a group that must
87 be executed before the group that ", World!" is in. To do this, we
88 can supply an extra parameter at the beginning of the
89 <code>connect</code> call that specifies the group. Group values
90 are, by default, <code>int</code>s, and are ordered by the integer
91 &lt; relation. Here's how we construct Hello, World:</para>
92 <programlisting><xi:include href="hello_world_ordered_code_snippet.xml"
93 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
94 <para>Invoking the signal will correctly print "Hello, World!", because the
95 <code>Hello</code> object is in group 0, which precedes group 1 where
96 the <code>World</code> object resides. The group
97 parameter is, in fact, optional. We omitted it in the first Hello,
98 World example because it was unnecessary when all of the slots are
99 independent. So what happens if we mix calls to connect that use the
100 group parameter and those that don't? The "unnamed" slots (i.e., those
101 that have been connected without specifying a group name) can be
102 placed at the front or back of the slot list (by passing
103 <code>boost::signals2::at_front</code> or <code>boost::signals2::at_back</code>
104 as the last parameter to <code><methodname
105 alt="boost::signals2::signal::connect">connect</methodname></code>, respectively),
106 and default to the end of the list. When
107 a group is specified, the final <code>at_front</code> or <code>at_back</code>
108 parameter describes where the slot
109 will be placed within the group ordering. Ungrouped slots connected with
110 <code>at_front</code> will always precede all grouped slots. Ungrouped
111 slots connected with <code>at_back</code> will always succeed all
112 grouped slots.
113 </para>
114 <para>
115 If we add a new slot to our example like this:
116 </para>
117 <programlisting><xi:include href="good_morning_def_code_snippet.xml"
118 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
119 <programlisting><xi:include href="hello_world_ordered_invoke_code_snippet.xml"
120 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
121 <para>... we will get the result we wanted:</para>
122 <programlisting>
123 Hello, World!
124 ... and good morning!
125 </programlisting>
126 </section>
127 </section>
128
129 <section><title>Passing Values to and from Slots</title>
130 <section><title>Slot Arguments (Beginner)</title>
131 <para>Signals can propagate arguments to each of the slots they call.
132 For instance, a signal that propagates mouse motion events might
133 want to pass along the new mouse coordinates and whether the mouse
134 buttons are pressed.</para>
135 <para>As an example, we'll create a signal that passes two
136 <code>float</code> arguments to its slots. Then we'll create a few
137 slots that print the results of various arithmetic operations on
138 these values.</para>
139 <programlisting><xi:include href="slot_arguments_slot_defs_code_snippet.xml"
140 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
141 <programlisting><xi:include href="slot_arguments_main_code_snippet.xml"
142 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
143 <para>This program will print out the following:</para>
144 <programlisting>The arguments are 5 and 3
145 The sum is 8
146 The product is 15
147 The difference is 2
148 The quotient is 1.66667</programlisting>
149 <para>So any values that are given to <code>sig</code> when it is
150 called like a function are passed to each of the slots. We have to
151 declare the types of these values up front when we create the
152 signal. The type <code><classname>boost::signals2::signal</classname>&lt;void (float,
153 float)&gt;</code> means that the signal has a <code>void</code>
154 return value and takes two <code>float</code> values. Any slot
155 connected to <code>sig</code> must therefore be able to take two
156 <code>float</code> values.</para>
157 </section>
158
159 <section><title>Signal Return Values (Advanced)</title>
160 <para>Just as slots can receive arguments, they can also return
161 values. These values can then be returned back to the caller of the
162 signal through a <firstterm>combiner</firstterm>. The combiner is a mechanism
163 that can take the results of calling slots (there may be no
164 results or a hundred; we don't know until the program runs) and
165 coalesces them into a single result to be returned to the caller.
166 The single result is often a simple function of the results of the
167 slot calls: the result of the last slot call, the maximum value
168 returned by any slot, or a container of all of the results are some
169 possibilities.</para>
170 <para>We can modify our previous arithmetic operations example
171 slightly so that the slots all return the results of computing the
172 product, quotient, sum, or difference. Then the signal itself can
173 return a value based on these results to be printed:</para>
174 <programlisting><xi:include href="signal_return_value_slot_defs_code_snippet.xml"
175 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
176 <programlisting>boost::signals2::signal&lt;float (float, float)&gt; sig;</programlisting>
177 <programlisting><xi:include href="signal_return_value_main_code_snippet.xml"
178 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
179
180 <para>This example program will output <code>2</code>. This is because the
181 default behavior of a signal that has a return type
182 (<code>float</code>, the first template argument given to the
183 <code><classname>boost::signals2::signal</classname></code> class template) is to call all slots and
184 then return a <classname>boost::optional</classname> containing
185 the result returned by the last slot called. This
186 behavior is admittedly silly for this example, because slots have
187 no side effects and the result is the last slot connected.</para>
188 <para>A more interesting signal result would be the maximum of the
189 values returned by any slot. To do this, we create a custom
190 combiner that looks like this:</para>
191 <programlisting><xi:include href="custom_combiners_maximum_def_code_snippet.xml"
192 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
193 <para>The <code>maximum</code> class template acts as a function
194 object. Its result type is given by its template parameter, and
195 this is the type it expects to be computing the maximum based on
196 (e.g., <code>maximum&lt;float&gt;</code> would find the maximum
197 <code>float</code> in a sequence of <code>float</code>s). When a
198 <code>maximum</code> object is invoked, it is given an input
199 iterator sequence <code>[first, last)</code> that includes the
200 results of calling all of the slots. <code>maximum</code> uses this
201 input iterator sequence to calculate the maximum element, and
202 returns that maximum value.</para>
203 <para>We actually use this new function object type by installing it
204 as a combiner for our signal. The combiner template argument
205 follows the signal's calling signature:</para>
206 <programlisting>
207 <classname>boost::signals2::signal</classname>&lt;float (float x, float y),
208 maximum&lt;float&gt; &gt; sig;
209 </programlisting>
210 <para>Now we can connect slots that perform arithmetic functions and
211 use the signal:</para>
212 <programlisting><xi:include href="custom_combiners_maximum_usage_code_snippet.xml"
213 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
214 <para>The output of this program will be <code>15</code>, because
215 regardless of the order in which the slots are connected, the product
216 of 5 and 3 will be larger than the quotient, sum, or
217 difference.</para>
218 <para>In other cases we might want to return all of the values
219 computed by the slots together, in one large data structure. This
220 is easily done with a different combiner:</para>
221 <programlisting><xi:include href="custom_combiners_aggregate_values_def_code_snippet.xml"
222 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
223 <para>
224 Again, we can create a signal with this new combiner:
225 </para>
226 <programlisting>
227 <classname>boost::signals2::signal</classname>&lt;float (float, float),
228 aggregate_values&lt;std::vector&lt;float&gt; &gt; &gt; sig;</programlisting>
229 <programlisting><xi:include href="custom_combiners_aggregate_values_usage_code_snippet.xml"
230 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
231 <para>The output of this program will contain 15, 8, 1.6667, and 2. It
232 is interesting here that
233 the first template argument for the <code>signal</code> class,
234 <code>float</code>, is not actually the return type of the signal.
235 Instead, it is the return type used by the connected slots and will
236 also be the <code>value_type</code> of the input iterators passed
237 to the combiner. The combiner itself is a function object and its
238 <code>result_type</code> member type becomes the return type of the
239 signal.</para>
240 <para>The input iterators passed to the combiner transform dereference
241 operations into slot calls. Combiners therefore have the option to
242 invoke only some slots until some particular criterion is met. For
243 instance, in a distributed computing system, the combiner may ask
244 each remote system whether it will handle the request. Only one
245 remote system needs to handle a particular request, so after a
246 remote system accepts the work we do not want to ask any other
247 remote systems to perform the same task. Such a combiner need only
248 check the value returned when dereferencing the iterator, and
249 return when the value is acceptable. The following combiner returns
250 the first non-NULL pointer to a <code>FulfilledRequest</code> data
251 structure, without asking any later slots to fulfill the
252 request:</para>
253 <programlisting>
254 struct DistributeRequest {
255 typedef FulfilledRequest* result_type;
256
257 template&lt;typename InputIterator&gt;
258 result_type operator()(InputIterator first, InputIterator last) const
259 {
260 while (first != last) {
261 if (result_type fulfilled = *first)
262 return fulfilled;
263 ++first;
264 }
265 return 0;
266 }
267 };
268 </programlisting>
269 </section>
270 </section>
271
272 <section><title>Connection Management</title>
273 <section><title>Disconnecting Slots (Beginner)</title>
274 <para>Slots aren't expected to exist indefinitely after they are
275 connected. Often slots are only used to receive a few events and
276 are then disconnected, and the programmer needs control to decide
277 when a slot should no longer be connected.</para>
278 <para>The entry point for managing connections explicitly is the
279 <code><classname>boost::signals2::connection</classname></code> class. The
280 <code>connection</code> class uniquely represents the connection
281 between a particular signal and a particular slot. The
282 <code><methodname alt="connection::connected">connected</methodname>()</code> method checks if the signal and slot are
283 still connected, and the <code><methodname alt="connection::disconnect">disconnect()</methodname></code> method
284 disconnects the signal and slot if they are connected before it is
285 called. Each call to the signal's <code>connect()</code> method
286 returns a connection object, which can be used to determine if the
287 connection still exists or to disconnect the signal and slot.</para>
288 <programlisting><xi:include href="disconnect_code_snippet.xml"
289 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
290 </section>
291
292 <section><title>Blocking Slots (Beginner)</title>
293
294 <para>Slots can be temporarily "blocked", meaning that they will be
295 ignored when the signal is invoked but have not been permanently disconnected.
296 This is typically used to prevent infinite recursion in cases where
297 otherwise running a slot would cause the signal it is connected to to be
298 invoked again. A
299 <classname>boost::signals2::shared_connection_block</classname> object will
300 temporarily block a slot. The connection is unblocked by either
301 destroying or calling
302 <methodname alt="shared_connection_block::unblock">unblock</methodname>
303 on all the
304 <code>shared_connection_block</code> objects that reference the connection.
305 Here is an example of
306 blocking/unblocking slots:</para>
307
308 <programlisting><xi:include href="block_code_snippet.xml"
309 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
310
311 </section>
312
313 <section><title>Scoped Connections (Intermediate)</title>
314 <para>The <classname>boost::signals2::scoped_connection</classname> class
315 references a signal/slot connection that will be disconnected when
316 the <code>scoped_connection</code> class goes out of scope. This
317 ability is useful when a connection need only be temporary,
318 e.g.,</para>
319 <programlisting><xi:include href="scoped_connection_code_snippet.xml"
320 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
321
322 <para>
323 Note, attempts to initialize a scoped_connection with the assignment syntax
324 will fail due to it being noncopyable. Either the explicit initialization syntax
325 or default construction followed by assignment from a <classname>signals2::connection</classname>
326 will work:
327 </para>
328 <programlisting>
329 // doesn't compile due to compiler attempting to copy a temporary scoped_connection object
330 // boost::signals2::scoped_connection c0 = sig.<methodname>connect</methodname>(ShortLived());
331
332 // okay
333 boost::signals2::scoped_connection c1(sig.<methodname>connect</methodname>(ShortLived()));
334
335 // also okay
336 boost::signals2::scoped_connection c2;
337 c2 = sig.<methodname>connect</methodname>(ShortLived());
338 </programlisting>
339 </section>
340
341 <section><title>Disconnecting Equivalent Slots (Intermediate)</title>
342 <para>One can disconnect slots that are equivalent to a given function
343 object using a form of the
344 <code><methodname>signal::disconnect</methodname></code> method, so long as
345 the type of the function object has an accessible <code>==</code>
346 operator. For instance:
347
348 </para>
349 <programlisting><xi:include href="disconnect_by_slot_def_code_snippet.xml"
350 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
351 <programlisting><classname>boost::signals2::signal</classname>&lt;void ()&gt; sig;</programlisting>
352 </section>
353 <programlisting><xi:include href="disconnect_by_slot_usage_code_snippet.xml"
354 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
355
356 <section id="signals2.tutorial.connection-management"><title>Automatic Connection Management (Intermediate)</title>
357 <para>Boost.Signals2 can automatically track the lifetime of objects
358 involved in signal/slot connections, including automatic
359 disconnection of slots when objects involved in the slot call are
360 destroyed. For instance, consider a simple news delivery service,
361 where clients connect to a news provider that then sends news to
362 all connected clients as information arrives. The news delivery
363 service may be constructed like this: </para>
364 <programlisting>
365 class NewsItem { /* ... */ };
366
367 typedef boost::signals2::signal&lt;void (const NewsItem&amp;)&gt; signal_type;
368 signal_type deliverNews;
369 </programlisting>
370
371 <para>Clients that wish to receive news updates need only connect a
372 function object that can receive news items to the
373 <code>deliverNews</code> signal. For instance, we may have a
374 special message area in our application specifically for news,
375 e.g.,:</para>
376 <programlisting>
377 struct NewsMessageArea : public MessageArea
378 {
379 public:
380 // ...
381
382 void displayNews(const NewsItem&amp; news) const
383 {
384 messageText = news.text();
385 update();
386 }
387 };
388
389 // ...
390 NewsMessageArea *newsMessageArea = new NewsMessageArea(/* ... */);
391 // ...
392 deliverNews.<methodname>connect</methodname>(boost::bind(&amp;NewsMessageArea::displayNews,
393 newsMessageArea, _1));
394 </programlisting>
395 <para>However, what if the user closes the news message area,
396 destroying the <code>newsMessageArea</code> object that
397 <code>deliverNews</code> knows about? Most likely, a segmentation
398 fault will occur. However, with Boost.Signals2 one may track any object
399 which is managed by a shared_ptr, by using
400 <methodname alt="boost::signals2::slot::track">slot::track</methodname>. A slot will automatically
401 disconnect when any of its tracked objects expire. In
402 addition, Boost.Signals2 will ensure that no tracked object expires
403 while the slot it is associated with is in mid-execution. It does so by creating
404 temporary shared_ptr copies of the slot's tracked objects before executing it.
405 To track <code>NewsMessageArea</code>, we use a shared_ptr to manage
406 its lifetime, and pass the shared_ptr to the slot via its
407 <methodname alt="boost::signals2::slot::track">slot::track</methodname>
408 method before connecting it,
409 e.g.:</para>
410 <programlisting>
411 // ...
412 boost::shared_ptr&lt;NewsMessageArea&gt; newsMessageArea(new NewsMessageArea(/* ... */));
413 // ...
414 deliverNews.<methodname>connect</methodname>(signal_type::slot_type(&amp;NewsMessageArea::displayNews,
415 newsMessageArea.get(), _1).track(newsMessageArea));
416 </programlisting>
417 <para>
418 Note there is no explicit call to bind() needed in the above example. If the
419 <classname>signals2::slot</classname> constructor is passed more than one
420 argument, it will automatically pass all the arguments to <code>bind</code> and use the
421 returned function object.
422 </para>
423 <para>Also note, we pass an ordinary pointer as the
424 second argument to the slot constructor, using <code>newsMessageArea.get()</code>
425 instead of passing the <code>shared_ptr</code> itself. If we had passed the
426 <code>newsMessageArea</code> itself, a copy of the <code>shared_ptr</code> would
427 have been bound into the slot function, preventing the <code>shared_ptr</code>
428 from expiring. However, the use of
429 <methodname alt="boost::signals2::slot::track">slot::track</methodname>
430 implies we wish to allow the tracked object to expire, and automatically
431 disconnect the connection when this occurs.
432 </para>
433 <para>
434 <code>shared_ptr</code> classes other than <classname>boost::shared_ptr</classname>
435 (such as <code>std::shared_ptr</code>) may also be tracked for connection management
436 purposes. They are supported by the <methodname>slot::track_foreign</methodname> method.
437 </para>
438 </section>
439
440 <section id="signals2.tutorial.deconstruct">
441 <title>Postconstructors and Predestructors (Advanced)</title>
442 <para>One limitation of using <code>shared_ptr</code> for tracking is that
443 an object cannot setup tracking of itself in its constructor. However, it is
444 possible to set up tracking in a post-constructor which is called after the
445 object has been created and passed to a <classname>shared_ptr</classname>.
446 The Boost.Signals2
447 library provides support for post-constructors and pre-destructors
448 via the <functionname>deconstruct()</functionname> factory function.
449 </para>
450 <para>
451 For most cases, the simplest and most robust way to setup postconstructors
452 for a class is to define an associated <code>adl_postconstruct</code> function
453 which can be found by <functionname>deconstruct()</functionname>,
454 make the class' constructors private, and give <functionname>deconstruct</functionname>
455 access to the private constructors by declaring <classname>deconstruct_access</classname>
456 a friend. This will ensure that objects of the class may only be created
457 through the <functionname>deconstruct()</functionname> function, and their
458 associated <code>adl_postconstruct()</code> function will always be called.
459 </para>
460 <para>The <link linkend="signals2.examples.deconstruct">examples</link> section
461 contains several examples of defining classes with postconstructors and
462 predestructors, and creating objects of these classes using
463 <functionname>deconstruct()</functionname>
464 </para>
465 <para>
466 Be aware that the postconstructor/predestructor support in Boost.Signals2
467 is in no way essential to the use of the library. The use of
468 <functionname>deconstruct</functionname>
469 is purely optional. One alternative is to
470 define static factory functions for your classes. The
471 factory function can create an object, pass ownership of the object to
472 a <classname>shared_ptr</classname>, setup tracking for the object,
473 then return the <classname>shared_ptr</classname>.
474 </para>
475 </section>
476
477 <section><title>When Can Disconnections Occur? (Intermediate)</title>
478 <para>Signal/slot disconnections occur when any of these conditions
479 occur:</para>
480 <itemizedlist>
481 <listitem><para>The connection is explicitly disconnected via the connection's
482 <code>disconnect</code> method directly, or indirectly via the
483 signal's <code>disconnect</code> method, or
484 <code>scoped_connection</code>'s destructor.</para></listitem>
485 <listitem><para>An object tracked by the slot is
486 destroyed.</para></listitem>
487 <listitem><para>The signal is destroyed.</para></listitem></itemizedlist>
488 <para>These events can occur at any time without disrupting a signal's
489 calling sequence. If a signal/slot connection is disconnected at
490 any time during a signal's calling sequence, the calling sequence
491 will still continue but will not invoke the disconnected slot.
492 Additionally, a signal may be destroyed while it is in a calling
493 sequence, and which case it will complete its slot call sequence
494 but may not be accessed directly.</para>
495 <para>Signals may be invoked recursively (e.g., a signal A calls a
496 slot B that invokes signal A...). The disconnection behavior does
497 not change in the recursive case, except that the slot calling
498 sequence includes slot calls for all nested invocations of the
499 signal.</para>
500 <para>
501 Note, even after a connection is disconnected, its's associated slot
502 may still be in the process of executing. In other words, disconnection
503 does not block waiting for the connection's associated slot to complete execution.
504 This situation may occur in a multi-threaded environment if the
505 disconnection occurs concurrently with signal invocation,
506 or in a single-threaded environment if a slot disconnects itself.
507 </para>
508 </section>
509
510 <section><title>Passing Slots (Intermediate)</title>
511 <para>Slots in the Boost.Signals2 library are created from arbitrary
512 function objects, and therefore have no fixed type. However, it is
513 commonplace to require that slots be passed through interfaces that
514 cannot be templates. Slots can be passed via the
515 <code>slot_type</code> for each particular signal type and any
516 function object compatible with the signature of the signal can be
517 passed to a <code>slot_type</code> parameter. For instance:</para>
518 <programlisting><xi:include href="passing_slots_defs_code_snippet.xml"
519 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
520 <programlisting>
521 <xi:include href="passing_slots_usage_code_snippet.xml"
522 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
523
524 <para>The <code>doOnClick</code> method is now functionally equivalent
525 to the <code>connect</code> method of the <code>onClick</code>
526 signal, but the details of the <code>doOnClick</code> method can be
527 hidden in an implementation detail file.</para>
528 </section>
529 </section>
530
531 <section id="signals2.tutorial.document-view">
532 <title>Example: Document-View</title>
533
534 <para>Signals can be used to implement flexible Document-View
535 architectures. The document will contain a signal to which each of
536 the views can connect. The following <code>Document</code> class
537 defines a simple text document that supports mulitple views. Note
538 that it stores a single signal to which all of the views will be
539 connected.</para>
540
541 <programlisting><xi:include href="document_def_code_snippet.xml"
542 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
543
544 <para>
545 Next, we can begin to define views. The
546 following <code>TextView</code> class provides a simple view of the
547 document text.
548 </para>
549
550 <programlisting><xi:include href="text_view_def_code_snippet.xml"
551 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
552
553 <para>Alternatively, we can provide a view of the document
554 translated into hex values using the <code>HexView</code>
555 view:</para>
556
557 <programlisting><xi:include href="hex_view_def_code_snippet.xml"
558 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
559
560 <para>
561 To tie the example together, here is a
562 simple <code>main</code> function that sets up two views and then
563 modifies the document:
564 </para>
565
566 <programlisting><xi:include href="document_view_main_code_snippet.xml"
567 xmlns:xi="http://www.w3.org/2001/XInclude" parse="xml"/></programlisting>
568
569 <para>The complete example source, contributed by Keith MacDonald,
570 is available in the <link linkend="signals2.examples.document-view">examples</link> section.
571 We also provide variations on the program which employ automatic connection management
572 to disconnect views on their destruction.
573 </para>
574 </section>
575
576 <section id="signals2.tutorial.extended-slot-type">
577 <title>Giving a Slot Access to its Connection (Advanced)</title>
578 <para>
579 You may encounter situations where you wish to disconnect or block a slot's
580 connection from within the slot itself. For example, suppose you have a group
581 of asynchronous tasks, each of which emits a signal when it completes.
582 You wish to connect a slot to all the tasks to retrieve their results as
583 each completes. Once a
584 given task completes and the slot is run, the slot no longer needs to be
585 connected to the completed task.
586 Therefore, you may wish to clean up old connections by having the slot
587 disconnect its invoking connection when it runs.
588 </para>
589 <para>
590 For a slot to disconnect (or block) its invoking connection, it must have
591 access to a <classname>signals2::connection</classname> object which references
592 the invoking signal-slot connection. The difficulty is,
593 the <code>connection</code> object is returned by the
594 <methodname>signal::connect</methodname>
595 method, and therefore is not available until after the slot is
596 already connected to the signal. This can be particularly troublesome
597 in a multi-threaded environment where the signal may be invoked
598 concurrently by a different thread while the slot is being connected.
599 </para>
600 <para>
601 Therefore, the signal classes provide
602 <methodname>signal::connect_extended</methodname>
603 methods, which allow slots which take an extra argument to be connected to a signal.
604 The extra argument is a <classname>signals2::connection</classname> object which refers
605 to the signal-slot connection currently invoking the slot.
606 <methodname>signal::connect_extended</methodname>
607 uses slots of the type given by the
608 <classname>signal::extended_slot_type</classname>
609 typedef.
610 </para>
611 <para>
612 The examples section includes an
613 <link linkend="signals2.examples.tutorial.extended_slot">extended_slot</link>
614 program which demonstrates the syntax for using
615 <methodname>signal::connect_extended</methodname>.
616 </para>
617 </section>
618
619 <section id="signals2.tutorial.signal-mutex-template-parameter">
620 <title>Changing the <code>Mutex</code> Type of a Signal (Advanced).</title>
621 <para>
622 For most cases the default type of <classname>boost::signals2::mutex</classname> for
623 a <classname>signals2::signal</classname>'s <code>Mutex</code> template type parameter should
624 be fine. If you wish to use an alternate mutex type, it must be default-constructible
625 and fulfill the <code>Lockable</code> concept defined by the Boost.Thread library.
626 That is, it must have <code>lock()</code> and <code>unlock()</code> methods
627 (the <code>Lockable</code> concept also includes a <code>try_lock()</code> method
628 but this library does not require try locking).
629 </para>
630 <para>
631 The Boost.Signals2 library provides one alternate mutex class for use with <code>signal</code>:
632 <classname>boost::signals2::dummy_mutex</classname>. This is a fake mutex for
633 use in single-threaded programs, where locking a real mutex would be useless
634 overhead. Other mutex types you could use with <code>signal</code> include
635 <classname>boost::mutex</classname>, or the <code>std::mutex</code> from
636 C++11.
637 </para>
638 <para>
639 Changing a signal's <code>Mutex</code> template type parameter can be tedious, due to
640 the large number of template parameters which precede it. The
641 <classname>signal_type</classname> metafunction is particularly useful in this case,
642 since it enables named template type parameters for the <classname>signals2::signal</classname>
643 class. For example, to declare a signal which takes an <code>int</code> as
644 an argument and uses a <classname>boost::signals2::dummy_mutex</classname>
645 for its <code>Mutex</code> types, you could write:
646 </para>
647 <programlisting>namespace bs2 = boost::signals2;
648 using namespace bs2::keywords;
649 bs2::signal_type&lt;void (int), mutex_type&lt;bs2::dummy_mutex&gt; &gt;::type sig;
650 </programlisting>
651
652 </section>
653
654 <section>
655 <title>Linking against the Signals2 library</title>
656 <para>Unlike the original Boost.Signals library, Boost.Signals2 is currently header-only.
657 </para>
658 </section>
659
660 </section>