//
-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Next we declare an object of type boost::asio::steady_timer. The core asio classes
that provide I/O functionality (or as in this case timer functionality) always
-take a reference to an io_context as their first constructor argument. The
-second argument to the constructor sets the timer to expire 5 seconds from now.
+take an executor, or a reference to an execution context (such as
+boost::asio::io_context), as their first constructor argument. The second argument to
+the constructor sets the timer to expire 5 seconds from now.
\until boost::asio::steady_timer
/**
\page tuttimer2 Timer.2 - Using a timer asynchronously
-This tutorial program demonstrates how to use asio's asynchronous callback
-functionality by modifying the program from tutorial Timer.1 to perform an
-asynchronous wait on the timer.
+This tutorial program demonstrates how to use asio's asynchronous functionality
+by modifying the program from tutorial Timer.1 to perform an asynchronous wait
+on the timer.
\dontinclude timer2/timer.cpp
\skip #include
\until asio.hpp
-Using asio's asynchronous functionality means having a callback
-function that will be called when an asynchronous operation completes. In this
-program we define a function called <tt>print</tt> to be called when the
-asynchronous wait finishes.
+Using asio's asynchronous functionality means supplying a @ref completion_token,
+which determines how the result will be delivered to a <em>completion
+handler</em> when an @ref asynchronous_operation completes. In this program we
+define a function called <tt>print</tt> to be called when the asynchronous wait
+finishes.
\until boost::asio::steady_timer
Next, instead of doing a blocking wait as in tutorial Timer.1,
we call the boost::asio::steady_timer::async_wait() function to perform an
asynchronous wait. When calling this function we pass the <tt>print</tt>
-callback handler that was defined above.
+function that was defined above.
\skipline async_wait
Finally, we must call the boost::asio::io_context::run() member function
on the io_context object.
-The asio library provides a guarantee that callback handlers will <b>only</b>
+The asio library provides a guarantee that completion handlers will <b>only</b>
be called from threads that are currently calling boost::asio::io_context::run().
-Therefore unless the boost::asio::io_context::run() function is called the callback for
-the asynchronous wait completion will never be invoked.
+Therefore unless the boost::asio::io_context::run() function is called the completion
+handler for the asynchronous wait completion will never be invoked.
The boost::asio::io_context::run() function will also continue to run while there is
still "work" to do. In this example, the work is the asynchronous wait on the
timer, so the call will not return until the timer has expired and the
-callback has completed.
+completion handler has returned.
It is important to remember to give the io_context some work to do before
calling boost::asio::io_context::run(). For example, if we had omitted the above call
*/
/**
-\page tuttimer3 Timer.3 - Binding arguments to a handler
+\page tuttimer3 Timer.3 - Binding arguments to a completion handler
In this tutorial we will modify the program from tutorial Timer.2 so that the
timer fires once a second. This will show how to pass additional parameters to
\until bind.hpp
To implement a repeating timer using asio you need to change
-the timer's expiry time in your callback function, and to then start a new
-asynchronous wait. Obviously this means that the callback function will need
+the timer's expiry time in your completion handler, and to then start a new
+asynchronous wait. Obviously this means that the completion handler will need
to be able to access the timer object. To this end we add two new parameters
to the <tt>print</tt> function:
-\li A pointer to a timer object.
+\li a pointer to a timer object; and
-\li A counter so that we can stop the program when the timer fires for the
-sixth time.
+\li a counter so that we can stop the program when the timer fires for the
+sixth time
+
+at the end of the parameter list.
\until {
Then we start a new asynchronous wait on the timer. As you can
see, the boost::bind() function is used to associate the extra parameters
-with your callback handler. The boost::asio::steady_timer::async_wait() function
+with your completion handler. The boost::asio::steady_timer::async_wait() function
expects a handler function (or function object) with the signature
<tt>void(const boost::system::error_code&)</tt>. Binding the additional parameters
converts your <tt>print</tt> function into a function object that matches the
the asynchronous operation, and if using boost::bind(), you must specify only
the arguments that match the handler's parameter list. In tutorial Timer.4 you
will see that this placeholder may be elided if the parameter is not needed by
-the callback handler.
+the completion handler.
\until boost::asio::io_context
*/
/**
-\page tuttimer4 Timer.4 - Using a member function as a handler
+\page tuttimer4 Timer.4 - Using a member function as a completion handler
-In this tutorial we will see how to use a class member function as a callback
+In this tutorial we will see how to use a class member function as a completion
handler. The program should execute identically to the tutorial program from
tutorial Timer.3.
\until bind.hpp
Instead of defining a free function <tt>print</tt> as the
-callback handler, as we did in the earlier tutorial programs, we now define a
+completion handler, as we did in the earlier tutorial programs, we now define a
class called <tt>printer</tt>.
\until public
member functions as with free functions. Since all non-static class member
functions have an implicit <tt>this</tt> parameter, we need to bind
<tt>this</tt> to the function. As in tutorial Timer.3, boost::bind()
-converts our callback handler (now a member function) into a function object
+converts our completion handler (now a member function) into a function object
that can be invoked as though it has the signature <tt>void(const
boost::system::error_code&)</tt>.
*/
/**
-\page tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs
+\page tuttimer5 Timer.5 - Synchronising completion handlers in multithreaded programs
This tutorial demonstrates the use of the boost::asio::strand class template to
-synchronise callback handlers in a multithreaded program.
+synchronise completion handlers in a multithreaded program.
The previous four tutorials avoided the issue of handler synchronisation by
calling the boost::asio::io_context::run() function from one thread only. As you
-already know, the asio library provides a guarantee that callback handlers will
-<b>only</b> be called from threads that are currently calling
+already know, the asio library provides a guarantee that completion handlers
+will <b>only</b> be called from threads that are currently calling
boost::asio::io_context::run(). Consequently, calling boost::asio::io_context::run() from
-only one thread ensures that callback handlers cannot run concurrently.
+only one thread ensures that completion handlers cannot run concurrently.
The single threaded approach is usually the best place to start when
developing applications using asio. The downside is the limitations it places
\until {
-When initiating the asynchronous operations, each callback handler is "bound"
+When initiating the asynchronous operations, each completion handler is "bound"
to an boost::asio::strand<boost::asio::io_context::executor_type> object. The
boost::asio::bind_executor() function returns a new handler that automatically
dispatches its contained handler through the boost::asio::strand object. By