]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
7c673cae
FG
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<!--
5Copyright Douglas Gregor 2001-2004
6Copyright Frank Mori Hess 2007-2009
7
8Distributed under the Boost Software License, Version 1.0. (See accompanying
9file 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
22structure roughly separates different concepts in the library
23(e.g., handling calling multiple slots, passing values to and from
24slots) and in each of these concepts the basic ideas are presented
25first and then more complex uses of the library are described
26later. Each of the sections is marked <emphasis>Beginner</emphasis>,
27<emphasis>Intermediate</emphasis>, or <emphasis>Advanced</emphasis> to help guide the
28reader. The <emphasis>Beginner</emphasis> sections include information that all
29library users should know; one can make good use of the Signals2
30library after having read only the <emphasis>Beginner</emphasis> sections. The
31<emphasis>Intermediate</emphasis> sections build on the <emphasis>Beginner</emphasis>
32sections with slightly more complex uses of the library. Finally,
33the <emphasis>Advanced</emphasis> sections detail very advanced uses of the
34Signals2 library, that often require a solid working knowledge of
35the <emphasis>Beginner</emphasis> and <emphasis>Intermediate</emphasis> topics; most users
36will 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
41slots. First, we create a signal <code>sig</code>, a signal that
42takes no arguments and has a void return value. Next, we connect
43the <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
46invokes <code>HelloWorld::operator()</code> to print "Hello,
47World!".</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
57we can make the Hello, World program more interesting by splitting
58the work of printing "Hello, World!" into two completely separate
59slots. The first slot will print "Hello" and may look like
60this:</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
64the 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
71signal, 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,
75so the output of this program will be as expected:</para>
76<programlisting>
77Hello, 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
83slots will have to be called before others even if they are not connected in that order. The Boost.Signals2
84library allows slots to be placed into groups that are ordered in
85some way. For our Hello, World program, we want "Hello" to be
86printed before ", World!", so we put "Hello" into a group that must
87be executed before the group that ", World!" is in. To do this, we
88can supply an extra parameter at the beginning of the
89<code>connect</code> call that specifies the group. Group values
90are, 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
96the <code>World</code> object resides. The group
97parameter is, in fact, optional. We omitted it in the first Hello,
98World example because it was unnecessary when all of the slots are
99independent. So what happens if we mix calls to connect that use the
100group parameter and those that don't? The "unnamed" slots (i.e., those
101that have been connected without specifying a group name) can be
102placed 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>
104as the last parameter to <code><methodname
105alt="boost::signals2::signal::connect">connect</methodname></code>, respectively),
106and default to the end of the list. When
107a group is specified, the final <code>at_front</code> or <code>at_back</code>
108parameter describes where the slot
109will be placed within the group ordering. Ungrouped slots connected with
110<code>at_front</code> will always precede all grouped slots. Ungrouped
111slots connected with <code>at_back</code> will always succeed all
112grouped 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>
123Hello, 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.
132For instance, a signal that propagates mouse motion events might
133want to pass along the new mouse coordinates and whether the mouse
134buttons 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
137slots that print the results of various arithmetic operations on
138these 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
145The sum is 8
146The product is 15
147The difference is 2
148The quotient is 1.66667</programlisting>
149<para>So any values that are given to <code>sig</code> when it is
150called like a function are passed to each of the slots. We have to
151declare the types of these values up front when we create the
152signal. The type <code><classname>boost::signals2::signal</classname>&lt;void (float,
153float)&gt;</code> means that the signal has a <code>void</code>
154return value and takes two <code>float</code> values. Any slot
155connected 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
161values. These values can then be returned back to the caller of the
162signal through a <firstterm>combiner</firstterm>. The combiner is a mechanism
163that can take the results of calling slots (there may be no
164results or a hundred; we don't know until the program runs) and
165coalesces them into a single result to be returned to the caller.
166The single result is often a simple function of the results of the
167slot calls: the result of the last slot call, the maximum value
168returned by any slot, or a container of all of the results are some
169possibilities.</para>
170<para>We can modify our previous arithmetic operations example
171slightly so that the slots all return the results of computing the
172product, quotient, sum, or difference. Then the signal itself can
173return 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
181default 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
184then return a <classname>boost::optional</classname> containing
185the result returned by the last slot called. This
186behavior is admittedly silly for this example, because slots have
187no side effects and the result is the last slot connected.</para>
188<para>A more interesting signal result would be the maximum of the
189values returned by any slot. To do this, we create a custom
190combiner 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
194object. Its result type is given by its template parameter, and
195this 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
199iterator sequence <code>[first, last)</code> that includes the
200results of calling all of the slots. <code>maximum</code> uses this
201input iterator sequence to calculate the maximum element, and
202returns that maximum value.</para>
203<para>We actually use this new function object type by installing it
204as a combiner for our signal. The combiner template argument
205follows 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
211use 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
215regardless of the order in which the slots are connected, the product
216of 5 and 3 will be larger than the quotient, sum, or
217difference.</para>
218<para>In other cases we might want to return all of the values
219computed by the slots together, in one large data structure. This
220is 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>
224Again, 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
232is interesting here that
233the first template argument for the <code>signal</code> class,
234<code>float</code>, is not actually the return type of the signal.
235Instead, it is the return type used by the connected slots and will
236also be the <code>value_type</code> of the input iterators passed
237to the combiner. The combiner itself is a function object and its
238<code>result_type</code> member type becomes the return type of the
239signal.</para>
240<para>The input iterators passed to the combiner transform dereference
241operations into slot calls. Combiners therefore have the option to
242invoke only some slots until some particular criterion is met. For
243instance, in a distributed computing system, the combiner may ask
244each remote system whether it will handle the request. Only one
245remote system needs to handle a particular request, so after a
246remote system accepts the work we do not want to ask any other
247remote systems to perform the same task. Such a combiner need only
248check the value returned when dereferencing the iterator, and
249return when the value is acceptable. The following combiner returns
250the first non-NULL pointer to a <code>FulfilledRequest</code> data
251structure, without asking any later slots to fulfill the
252request:</para>
253<programlisting>
254struct 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
275connected. Often slots are only used to receive a few events and
276are then disconnected, and the programmer needs control to decide
277when 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
281between 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
283still connected, and the <code><methodname alt="connection::disconnect">disconnect()</methodname></code> method
284disconnects the signal and slot if they are connected before it is
285called. Each call to the signal's <code>connect()</code> method
286returns a connection object, which can be used to determine if the
287connection 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
295ignored when the signal is invoked but have not been permanently disconnected.
296This is typically used to prevent infinite recursion in cases where
297otherwise running a slot would cause the signal it is connected to to be
298invoked again. A
299<classname>boost::signals2::shared_connection_block</classname> object will
300temporarily block a slot. The connection is unblocked by either
301destroying or calling
302<methodname alt="shared_connection_block::unblock">unblock</methodname>
303on all the
304<code>shared_connection_block</code> objects that reference the connection.
305Here is an example of
306blocking/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
315references a signal/slot connection that will be disconnected when
316the <code>scoped_connection</code> class goes out of scope. This
317ability is useful when a connection need only be temporary,
318e.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
333boost::signals2::scoped_connection c1(sig.<methodname>connect</methodname>(ShortLived()));
334
335// also okay
336boost::signals2::scoped_connection c2;
337c2 = 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
343object using a form of the
344<code><methodname>signal::disconnect</methodname></code> method, so long as
345the type of the function object has an accessible <code>==</code>
346operator. 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
358involved in signal/slot connections, including automatic
359disconnection of slots when objects involved in the slot call are
360destroyed. For instance, consider a simple news delivery service,
361where clients connect to a news provider that then sends news to
362all connected clients as information arrives. The news delivery
363service may be constructed like this: </para>
364<programlisting>
365class NewsItem { /* ... */ };
366
367typedef boost::signals2::signal&lt;void (const NewsItem&amp;)&gt; signal_type;
368signal_type deliverNews;
369</programlisting>
370
371<para>Clients that wish to receive news updates need only connect a
372function object that can receive news items to the
373<code>deliverNews</code> signal. For instance, we may have a
374special message area in our application specifically for news,
375e.g.,:</para>
376<programlisting>
377struct NewsMessageArea : public MessageArea
378{
379public:
380 // ...
381
382 void displayNews(const NewsItem&amp; news) const
383 {
384 messageText = news.text();
385 update();
386 }
387};
388
389// ...
390NewsMessageArea *newsMessageArea = new NewsMessageArea(/* ... */);
391// ...
392deliverNews.<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,
396destroying the <code>newsMessageArea</code> object that
397<code>deliverNews</code> knows about? Most likely, a segmentation
398fault will occur. However, with Boost.Signals2 one may track any object
399which is managed by a shared_ptr, by using
400<methodname alt="boost::signals2::slot::track">slot::track</methodname>. A slot will automatically
401disconnect when any of its tracked objects expire. In
402addition, Boost.Signals2 will ensure that no tracked object expires
403while the slot it is associated with is in mid-execution. It does so by creating
404temporary shared_ptr copies of the slot's tracked objects before executing it.
405To track <code>NewsMessageArea</code>, we use a shared_ptr to manage
406its lifetime, and pass the shared_ptr to the slot via its
407<methodname alt="boost::signals2::slot::track">slot::track</methodname>
408method before connecting it,
409e.g.:</para>
410<programlisting>
411// ...
412boost::shared_ptr&lt;NewsMessageArea&gt; newsMessageArea(new NewsMessageArea(/* ... */));
413// ...
414deliverNews.<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
479occur:</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
483signal'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
486destroyed.</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
489calling sequence. If a signal/slot connection is disconnected at
490any time during a signal's calling sequence, the calling sequence
491will still continue but will not invoke the disconnected slot.
492Additionally, a signal may be destroyed while it is in a calling
493sequence, and which case it will complete its slot call sequence
494but may not be accessed directly.</para>
495<para>Signals may be invoked recursively (e.g., a signal A calls a
496slot B that invokes signal A...). The disconnection behavior does
497not change in the recursive case, except that the slot calling
498sequence includes slot calls for all nested invocations of the
499signal.</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
512function objects, and therefore have no fixed type. However, it is
513commonplace to require that slots be passed through interfaces that
514cannot be templates. Slots can be passed via the
515<code>slot_type</code> for each particular signal type and any
516function object compatible with the signature of the signal can be
517passed 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
525to the <code>connect</code> method of the <code>onClick</code>
526signal, but the details of the <code>doOnClick</code> method can be
527hidden 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;
648using namespace bs2::keywords;
649bs2::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>