]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/asio/example/cpp03/tutorial/timer_dox.txt
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / asio / example / cpp03 / tutorial / timer_dox.txt
CommitLineData
7c673cae 1//
b32b8144 2// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
7c673cae
FG
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7
8/**
9\page tuttimer1 Timer.1 - Using a timer synchronously
10
11This tutorial program introduces asio by showing how to perform a blocking
12wait on a timer.
13
14\dontinclude timer1/timer.cpp
15\skip #include
16
17We start by including the necessary header files.
18
19All of the asio classes can be used by simply including the <tt>"asio.hpp"</tt>
20header file.
21
22\until asio.hpp
23
24Since this example uses timers, we need to include the appropriate
25Boost.Date_Time header file for manipulating times.
26
27\until posix_time.hpp
28
29All programs that use asio need to have at least one boost::asio::io_service object.
30This class provides access to I/O functionality. We declare an object of this
31type first thing in the main function.
32
33\until boost::asio::io_service
34
35Next we declare an object of type boost::asio::deadline_timer. The core asio classes
36that provide I/O functionality (or as in this case timer functionality) always
37take a reference to an io_service as their first constructor argument. The
38second argument to the constructor sets the timer to expire 5 seconds from now.
39
40\until boost::asio::deadline_timer
41
42In this simple example we perform a blocking wait on the timer.
43That is, the call to boost::asio::deadline_timer::wait() will not return until the
44timer has expired, 5 seconds after it was created (i.e. <b>not</b> from when the
45wait starts).
46
47A deadline timer is always in one of two states: "expired" or "not expired". If
48the boost::asio::deadline_timer::wait() function is called on an expired timer, it
49will return immediately.
50
51\until wait
52
53Finally we print the obligatory <tt>"Hello, world!"</tt>
54message to show when the timer has expired.
55
56\until }
57
58See the \ref tuttimer1src "full source listing" \n
59Return to the \ref index "tutorial index" \n
60Next: \ref tuttimer2
61
62*/
63
64/**
65\page tuttimer1src Source listing for Timer.1
66\include timer1/timer.cpp
67Return to \ref tuttimer1
68*/
69
70/**
71\page tuttimer2 Timer.2 - Using a timer asynchronously
72
73This tutorial program demonstrates how to use asio's asynchronous callback
74functionality by modifying the program from tutorial Timer.1 to perform an
75asynchronous wait on the timer.
76
77\dontinclude timer2/timer.cpp
78\skip #include
79
80\until posix_time.hpp
81
82Using asio's asynchronous functionality means having a callback
83function that will be called when an asynchronous operation completes. In this
84program we define a function called <tt>print</tt> to be called when the
85asynchronous wait finishes.
86
87\until boost::asio::deadline_timer
88
89Next, instead of doing a blocking wait as in tutorial Timer.1,
90we call the boost::asio::deadline_timer::async_wait() function to perform an
91asynchronous wait. When calling this function we pass the <tt>print</tt>
92callback handler that was defined above.
93
94\skipline async_wait
95
96Finally, we must call the boost::asio::io_service::run() member function
97on the io_service object.
98
99The asio library provides a guarantee that callback handlers will <b>only</b>
100be called from threads that are currently calling boost::asio::io_service::run().
101Therefore unless the boost::asio::io_service::run() function is called the callback for
102the asynchronous wait completion will never be invoked.
103
104The boost::asio::io_service::run() function will also continue to run while there is
105still "work" to do. In this example, the work is the asynchronous wait on the
106timer, so the call will not return until the timer has expired and the
107callback has completed.
108
109It is important to remember to give the io_service some work to do before
110calling boost::asio::io_service::run(). For example, if we had omitted the above call
111to boost::asio::deadline_timer::async_wait(), the io_service would not have had any
112work to do, and consequently boost::asio::io_service::run() would have returned
113immediately.
114
115\skip run
116\until }
117
118See the \ref tuttimer2src "full source listing" \n
119Return to the \ref index "tutorial index" \n
120Previous: \ref tuttimer1 \n
121Next: \ref tuttimer3
122
123*/
124
125/**
126\page tuttimer2src Source listing for Timer.2
127\include timer2/timer.cpp
128Return to \ref tuttimer2
129*/
130
131/**
132\page tuttimer3 Timer.3 - Binding arguments to a handler
133
134In this tutorial we will modify the program from tutorial Timer.2 so that the
135timer fires once a second. This will show how to pass additional parameters to
136your handler function.
137
138\dontinclude timer3/timer.cpp
139\skip #include
140
141\until posix_time.hpp
142
143To implement a repeating timer using asio you need to change
144the timer's expiry time in your callback function, and to then start a new
145asynchronous wait. Obviously this means that the callback function will need
146to be able to access the timer object. To this end we add two new parameters
147to the <tt>print</tt> function:
148
149\li A pointer to a timer object.
150
151\li A counter so that we can stop the program when the timer fires for the
152sixth time.
153
154\until {
155
156As mentioned above, this tutorial program uses a counter to
157stop running when the timer fires for the sixth time. However you will observe
158that there is no explicit call to ask the io_service to stop. Recall that in
159tutorial Timer.2 we learnt that the boost::asio::io_service::run() function completes
160when there is no more "work" to do. By not starting a new asynchronous wait on
161the timer when <tt>count</tt> reaches 5, the io_service will run out of work and
162stop running.
163
164\until ++
165
166Next we move the expiry time for the timer along by one second
167from the previous expiry time. By calculating the new expiry time relative to
168the old, we can ensure that the timer does not drift away from the
169whole-second mark due to any delays in processing the handler.
170
171\until expires_at
172
173Then we start a new asynchronous wait on the timer. As you can
174see, the boost::bind() function is used to associate the extra parameters
175with your callback handler. The boost::asio::deadline_timer::async_wait() function
176expects a handler function (or function object) with the signature
177<tt>void(const boost::system::error_code&)</tt>. Binding the additional parameters
178converts your <tt>print</tt> function into a function object that matches the
179signature correctly.
180
181See the <a href="http://www.boost.org/libs/bind/bind.html">Boost.Bind
182documentation</a> for more information on how to use boost::bind().
183
184In this example, the boost::asio::placeholders::error argument to boost::bind() is a
185named placeholder for the error object passed to the handler. When initiating
186the asynchronous operation, and if using boost::bind(), you must specify only
187the arguments that match the handler's parameter list. In tutorial Timer.4 you
188will see that this placeholder may be elided if the parameter is not needed by
189the callback handler.
190
191\until boost::asio::io_service
192
193A new <tt>count</tt> variable is added so that we can stop the
194program when the timer fires for the sixth time.
195
196\until boost::asio::deadline_timer
197
198As in Step 4, when making the call to
199boost::asio::deadline_timer::async_wait() from <tt>main</tt> we bind the additional
200parameters needed for the <tt>print</tt> function.
201
202\until run
203
204Finally, just to prove that the <tt>count</tt> variable was
205being used in the <tt>print</tt> handler function, we will print out its new
206value.
207
208\until }
209
210See the \ref tuttimer3src "full source listing" \n
211Return to the \ref index "tutorial index" \n
212Previous: \ref tuttimer2 \n
213Next: \ref tuttimer4
214
215*/
216
217/**
218\page tuttimer3src Source listing for Timer.3
219\include timer3/timer.cpp
220Return to \ref tuttimer3
221*/
222
223/**
224\page tuttimer4 Timer.4 - Using a member function as a handler
225
226In this tutorial we will see how to use a class member function as a callback
227handler. The program should execute identically to the tutorial program from
228tutorial Timer.3.
229
230\dontinclude timer4/timer.cpp
231\skip #include
232
233\until posix_time.hpp
234
235Instead of defining a free function <tt>print</tt> as the
236callback handler, as we did in the earlier tutorial programs, we now define a
237class called <tt>printer</tt>.
238
239\until public
240
241The constructor of this class will take a reference to the
242io_service object and use it when initialising the <tt>timer_</tt> member. The
243counter used to shut down the program is now also a member of the class.
244
245\until {
246
247The boost::bind() function works just as well with class
248member functions as with free functions. Since all non-static class member
249functions have an implicit <tt>this</tt> parameter, we need to bind
250<tt>this</tt> to the function. As in tutorial Timer.3, boost::bind()
251converts our callback handler (now a member function) into a function object
252that can be invoked as though it has the signature <tt>void(const
253boost::system::error_code&)</tt>.
254
255You will note that the boost::asio::placeholders::error placeholder is not specified
256here, as the <tt>print</tt> member function does not accept an error object as
257a parameter.
258
259\until }
260
261In the class destructor we will print out the final value of
262the counter.
263
264\until }
265
266The <tt>print</tt> member function is very similar to the
267<tt>print</tt> function from tutorial Timer.3, except that it now operates on
268the class data members instead of having the timer and counter passed in as
269parameters.
270
271\until };
272
273The <tt>main</tt> function is much simpler than before, as it
274now declares a local <tt>printer</tt> object before running the io_service as
275normal.
276
277\until }
278
279See the \ref tuttimer4src "full source listing" \n
280Return to the \ref index "tutorial index" \n
281Previous: \ref tuttimer3 \n
282Next: \ref tuttimer5 \n
283
284*/
285
286/**
287\page tuttimer4src Source listing for Timer.4
288\include timer4/timer.cpp
289Return to \ref tuttimer4
290*/
291
292/**
293\page tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs
294
b32b8144
FG
295This tutorial demonstrates the use of the boost::asio::io_service::strand class to
296synchronise callback handlers in a multithreaded program.
7c673cae
FG
297
298The previous four tutorials avoided the issue of handler synchronisation by
299calling the boost::asio::io_service::run() function from one thread only. As you
300already know, the asio library provides a guarantee that callback handlers will
301<b>only</b> be called from threads that are currently calling
302boost::asio::io_service::run(). Consequently, calling boost::asio::io_service::run() from
303only one thread ensures that callback handlers cannot run concurrently.
304
305The single threaded approach is usually the best place to start when
306developing applications using asio. The downside is the limitations it places
307on programs, particularly servers, including:
308
309<ul>
310<li>Poor responsiveness when handlers can take a long time to complete.</li>
311<li>An inability to scale on multiprocessor systems.</li>
312</ul>
313
314If you find yourself running into these limitations, an alternative approach
315is to have a pool of threads calling boost::asio::io_service::run(). However, as this
316allows handlers to execute concurrently, we need a method of synchronisation
317when handlers might be accessing a shared, thread-unsafe resource.
318
319\dontinclude timer5/timer.cpp
320\skip #include
321
322\until posix_time.hpp
323
324We start by defining a class called <tt>printer</tt>, similar
325to the class in the previous tutorial. This class will extend the previous
326tutorial by running two timers in parallel.
327
328\until public
329
330In addition to initialising a pair of boost::asio::deadline_timer members, the
331constructor initialises the <tt>strand_</tt> member, an object of type
b32b8144 332boost::asio::io_service::strand.
7c673cae 333
b32b8144
FG
334An boost::asio::io_service::strand is an executor that guarantees that, for those
335handlers that are dispatched through it, an executing handler will be allowed
336to complete before the next one is started. This is guaranteed irrespective of
337the number of threads that are calling boost::asio::io_service::run(). Of course, the
338handlers may still execute concurrently with other handlers that were
339<b>not</b> dispatched through an boost::asio::io_service::strand, or were dispatched
340through a different boost::asio::io_service::strand object.
7c673cae
FG
341
342\until {
343
b32b8144
FG
344When initiating the asynchronous operations, each callback handler is "bound"
345to an boost::asio::io_service::strand object. The
346boost::asio::io_service::strand::bind_executor() function returns a new handler that
347automatically dispatches its contained handler through the
348boost::asio::io_service::strand object. By binding the handlers to the same
349boost::asio::io_service::strand, we are ensuring that they cannot execute
350concurrently.
7c673cae
FG
351
352\until }
353\until }
354
355In a multithreaded program, the handlers for asynchronous
356operations should be synchronised if they access shared resources. In this
357tutorial, the shared resources used by the handlers (<tt>print1</tt> and
358<tt>print2</tt>) are <tt>std::cout</tt> and the <tt>count_</tt> data member.
359
360\until };
361
362The <tt>main</tt> function now causes boost::asio::io_service::run() to
363be called from two threads: the main thread and one additional thread. This is
364accomplished using an boost::thread object.
365
366Just as it would with a call from a single thread, concurrent calls to
367boost::asio::io_service::run() will continue to execute while there is "work" left to
368do. The background thread will not exit until all asynchronous operations have
369completed.
370
371\until }
372
373See the \ref tuttimer5src "full source listing" \n
374Return to the \ref index "tutorial index" \n
375Previous: \ref tuttimer4 \n
376
377*/
378
379/**
380\page tuttimer5src Source listing for Timer.5
381\include timer5/timer.cpp
382Return to \ref tuttimer5
383*/