2 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
9 \page tuttimer1 Timer.1 - Using a timer synchronously
11 This tutorial program introduces asio by showing how to perform a blocking
14 \dontinclude timer1/timer.cpp
17 We start by including the necessary header files.
19 All of the asio classes can be used by simply including the <tt>"asio.hpp"</tt>
24 All programs that use asio need to have at least one boost::asio::io_context object.
25 This class provides access to I/O functionality. We declare an object of this
26 type first thing in the main function.
28 \until boost::asio::io_context
30 Next we declare an object of type boost::asio::steady_timer. The core asio classes
31 that provide I/O functionality (or as in this case timer functionality) always
32 take a reference to an io_context as their first constructor argument. The
33 second argument to the constructor sets the timer to expire 5 seconds from now.
35 \until boost::asio::steady_timer
37 In this simple example we perform a blocking wait on the timer.
38 That is, the call to boost::asio::steady_timer::wait() will not return until the
39 timer has expired, 5 seconds after it was created (i.e. <b>not</b> from when the
42 A timer is always in one of two states: "expired" or "not expired". If the
43 boost::asio::steady_timer::wait() function is called on an expired timer, it will
48 Finally we print the obligatory <tt>"Hello, world!"</tt>
49 message to show when the timer has expired.
53 See the \ref tuttimer1src "full source listing" \n
54 Return to the \ref index "tutorial index" \n
60 \page tuttimer1src Source listing for Timer.1
61 \include timer1/timer.cpp
62 Return to \ref tuttimer1
66 \page tuttimer2 Timer.2 - Using a timer asynchronously
68 This tutorial program demonstrates how to use asio's asynchronous callback
69 functionality by modifying the program from tutorial Timer.1 to perform an
70 asynchronous wait on the timer.
72 \dontinclude timer2/timer.cpp
77 Using asio's asynchronous functionality means having a callback
78 function that will be called when an asynchronous operation completes. In this
79 program we define a function called <tt>print</tt> to be called when the
80 asynchronous wait finishes.
82 \until boost::asio::steady_timer
84 Next, instead of doing a blocking wait as in tutorial Timer.1,
85 we call the boost::asio::steady_timer::async_wait() function to perform an
86 asynchronous wait. When calling this function we pass the <tt>print</tt>
87 callback handler that was defined above.
91 Finally, we must call the boost::asio::io_context::run() member function
92 on the io_context object.
94 The asio library provides a guarantee that callback handlers will <b>only</b>
95 be called from threads that are currently calling boost::asio::io_context::run().
96 Therefore unless the boost::asio::io_context::run() function is called the callback for
97 the asynchronous wait completion will never be invoked.
99 The boost::asio::io_context::run() function will also continue to run while there is
100 still "work" to do. In this example, the work is the asynchronous wait on the
101 timer, so the call will not return until the timer has expired and the
102 callback has completed.
104 It is important to remember to give the io_context some work to do before
105 calling boost::asio::io_context::run(). For example, if we had omitted the above call
106 to boost::asio::steady_timer::async_wait(), the io_context would not have had any
107 work to do, and consequently boost::asio::io_context::run() would have returned
113 See the \ref tuttimer2src "full source listing" \n
114 Return to the \ref index "tutorial index" \n
115 Previous: \ref tuttimer1 \n
121 \page tuttimer2src Source listing for Timer.2
122 \include timer2/timer.cpp
123 Return to \ref tuttimer2
127 \page tuttimer3 Timer.3 - Binding arguments to a handler
129 In this tutorial we will modify the program from tutorial Timer.2 so that the
130 timer fires once a second. This will show how to pass additional parameters to
131 your handler function.
133 \dontinclude timer3/timer.cpp
138 To implement a repeating timer using asio you need to change
139 the timer's expiry time in your callback function, and to then start a new
140 asynchronous wait. Obviously this means that the callback function will need
141 to be able to access the timer object. To this end we add two new parameters
142 to the <tt>print</tt> function:
144 \li A pointer to a timer object.
146 \li A counter so that we can stop the program when the timer fires for the
151 As mentioned above, this tutorial program uses a counter to
152 stop running when the timer fires for the sixth time. However you will observe
153 that there is no explicit call to ask the io_context to stop. Recall that in
154 tutorial Timer.2 we learnt that the boost::asio::io_context::run() function completes
155 when there is no more "work" to do. By not starting a new asynchronous wait on
156 the timer when <tt>count</tt> reaches 5, the io_context will run out of work and
161 Next we move the expiry time for the timer along by one second
162 from the previous expiry time. By calculating the new expiry time relative to
163 the old, we can ensure that the timer does not drift away from the
164 whole-second mark due to any delays in processing the handler.
168 Then we start a new asynchronous wait on the timer. As you can
169 see, the boost::bind() function is used to associate the extra parameters
170 with your callback handler. The boost::asio::steady_timer::async_wait() function
171 expects a handler function (or function object) with the signature
172 <tt>void(const boost::system::error_code&)</tt>. Binding the additional parameters
173 converts your <tt>print</tt> function into a function object that matches the
176 See the <a href="http://www.boost.org/libs/bind/bind.html">Boost.Bind
177 documentation</a> for more information on how to use boost::bind().
179 In this example, the boost::asio::placeholders::error argument to boost::bind() is a
180 named placeholder for the error object passed to the handler. When initiating
181 the asynchronous operation, and if using boost::bind(), you must specify only
182 the arguments that match the handler's parameter list. In tutorial Timer.4 you
183 will see that this placeholder may be elided if the parameter is not needed by
184 the callback handler.
186 \until boost::asio::io_context
188 A new <tt>count</tt> variable is added so that we can stop the
189 program when the timer fires for the sixth time.
191 \until boost::asio::steady_timer
193 As in Step 4, when making the call to
194 boost::asio::steady_timer::async_wait() from <tt>main</tt> we bind the additional
195 parameters needed for the <tt>print</tt> function.
199 Finally, just to prove that the <tt>count</tt> variable was
200 being used in the <tt>print</tt> handler function, we will print out its new
205 See the \ref tuttimer3src "full source listing" \n
206 Return to the \ref index "tutorial index" \n
207 Previous: \ref tuttimer2 \n
213 \page tuttimer3src Source listing for Timer.3
214 \include timer3/timer.cpp
215 Return to \ref tuttimer3
219 \page tuttimer4 Timer.4 - Using a member function as a handler
221 In this tutorial we will see how to use a class member function as a callback
222 handler. The program should execute identically to the tutorial program from
225 \dontinclude timer4/timer.cpp
230 Instead of defining a free function <tt>print</tt> as the
231 callback handler, as we did in the earlier tutorial programs, we now define a
232 class called <tt>printer</tt>.
236 The constructor of this class will take a reference to the
237 io_context object and use it when initialising the <tt>timer_</tt> member. The
238 counter used to shut down the program is now also a member of the class.
242 The boost::bind() function works just as well with class
243 member functions as with free functions. Since all non-static class member
244 functions have an implicit <tt>this</tt> parameter, we need to bind
245 <tt>this</tt> to the function. As in tutorial Timer.3, boost::bind()
246 converts our callback handler (now a member function) into a function object
247 that can be invoked as though it has the signature <tt>void(const
248 boost::system::error_code&)</tt>.
250 You will note that the boost::asio::placeholders::error placeholder is not specified
251 here, as the <tt>print</tt> member function does not accept an error object as
256 In the class destructor we will print out the final value of
261 The <tt>print</tt> member function is very similar to the
262 <tt>print</tt> function from tutorial Timer.3, except that it now operates on
263 the class data members instead of having the timer and counter passed in as
268 The <tt>main</tt> function is much simpler than before, as it
269 now declares a local <tt>printer</tt> object before running the io_context as
274 See the \ref tuttimer4src "full source listing" \n
275 Return to the \ref index "tutorial index" \n
276 Previous: \ref tuttimer3 \n
277 Next: \ref tuttimer5 \n
282 \page tuttimer4src Source listing for Timer.4
283 \include timer4/timer.cpp
284 Return to \ref tuttimer4
288 \page tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs
290 This tutorial demonstrates the use of the boost::asio::strand class template to
291 synchronise callback handlers in a multithreaded program.
293 The previous four tutorials avoided the issue of handler synchronisation by
294 calling the boost::asio::io_context::run() function from one thread only. As you
295 already know, the asio library provides a guarantee that callback handlers will
296 <b>only</b> be called from threads that are currently calling
297 boost::asio::io_context::run(). Consequently, calling boost::asio::io_context::run() from
298 only one thread ensures that callback handlers cannot run concurrently.
300 The single threaded approach is usually the best place to start when
301 developing applications using asio. The downside is the limitations it places
302 on programs, particularly servers, including:
305 <li>Poor responsiveness when handlers can take a long time to complete.</li>
306 <li>An inability to scale on multiprocessor systems.</li>
309 If you find yourself running into these limitations, an alternative approach
310 is to have a pool of threads calling boost::asio::io_context::run(). However, as this
311 allows handlers to execute concurrently, we need a method of synchronisation
312 when handlers might be accessing a shared, thread-unsafe resource.
314 \dontinclude timer5/timer.cpp
319 We start by defining a class called <tt>printer</tt>, similar
320 to the class in the previous tutorial. This class will extend the previous
321 tutorial by running two timers in parallel.
325 In addition to initialising a pair of boost::asio::steady_timer members, the
326 constructor initialises the <tt>strand_</tt> member, an object of type
327 boost::asio::strand<boost::asio::io_context::executor_type>.
329 The boost::asio::strand class template is an executor adapter that guarantees
330 that, for those handlers that are dispatched through it, an executing handler
331 will be allowed to complete before the next one is started. This is guaranteed
332 irrespective of the number of threads that are calling
333 boost::asio::io_context::run(). Of course, the handlers may still execute
334 concurrently with other handlers that were <b>not</b> dispatched through an
335 boost::asio::strand, or were dispatched through a different boost::asio::strand
340 When initiating the asynchronous operations, each callback handler is "bound"
341 to an boost::asio::strand<boost::asio::io_context::executor_type> object. The
342 boost::asio::bind_executor() function returns a new handler that automatically
343 dispatches its contained handler through the boost::asio::strand object. By
344 binding the handlers to the same boost::asio::strand, we are ensuring that they
345 cannot execute concurrently.
350 In a multithreaded program, the handlers for asynchronous
351 operations should be synchronised if they access shared resources. In this
352 tutorial, the shared resources used by the handlers (<tt>print1</tt> and
353 <tt>print2</tt>) are <tt>std::cout</tt> and the <tt>count_</tt> data member.
357 The <tt>main</tt> function now causes boost::asio::io_context::run() to
358 be called from two threads: the main thread and one additional thread. This is
359 accomplished using an boost::thread object.
361 Just as it would with a call from a single thread, concurrent calls to
362 boost::asio::io_context::run() will continue to execute while there is "work" left to
363 do. The background thread will not exit until all asynchronous operations have
368 See the \ref tuttimer5src "full source listing" \n
369 Return to the \ref index "tutorial index" \n
370 Previous: \ref tuttimer4 \n
375 \page tuttimer5src Source listing for Timer.5
376 \include timer5/timer.cpp
377 Return to \ref tuttimer5