[DEV] add v1.76.0

This commit is contained in:
2021-10-05 21:37:46 +02:00
parent a97e9ae7d4
commit d0115b733d
45133 changed files with 4744437 additions and 1026325 deletions

View File

@@ -1,46 +1,33 @@
#
# Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
# Copyright (c) 2003-2021 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)
#
import os ;
if [ os.name ] = SOLARIS
{
lib socket ;
lib nsl ;
}
else if [ os.name ] = NT
{
lib ws2_32 ;
lib mswsock ;
}
else if [ os.name ] = HPUX
{
lib ipv6 ;
}
else if [ os.name ] = HAIKU
{
lib network ;
}
lib socket ; # SOLARIS
lib nsl ; # SOLARIS
lib ws2_32 ; # NT
lib mswsock ; # NT
lib ipv6 ; # HPUX
lib network ; # HAIKU
project
: requirements
<library>/boost/system//boost_system
<library>/boost/chrono//boost_chrono
<library>/boost/thread//boost_thread
<define>BOOST_ALL_NO_LIB=1
<threading>multi
<os>SOLARIS:<library>socket
<os>SOLARIS:<library>nsl
<os>NT:<define>_WIN32_WINNT=0x0501
<os>NT,<toolset>gcc:<library>ws2_32
<os>NT,<toolset>gcc:<library>mswsock
<os>NT,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
<os>HPUX,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
<os>HPUX:<library>ipv6
<os>HAIKU:<library>network
<target-os>solaris:<library>socket
<target-os>solaris:<library>nsl
<target-os>windows:<define>_WIN32_WINNT=0x0501
<target-os>windows,<toolset>gcc:<library>ws2_32
<target-os>windows,<toolset>gcc:<library>mswsock
<target-os>windows,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
<target-os>hpux,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
<target-os>hpux:<library>ipv6
<target-os>haiku:<library>network
;
obj timer1.obj : timer1/timer.cpp ;

View File

@@ -2,7 +2,7 @@
// client.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)

View File

@@ -2,7 +2,7 @@
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)

View File

@@ -2,7 +2,7 @@
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -11,7 +11,7 @@
#include <ctime>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/bind/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
@@ -70,7 +70,8 @@ class tcp_server
{
public:
tcp_server(boost::asio::io_context& io_context)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
: io_context_(io_context),
acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
{
start_accept();
}
@@ -79,7 +80,7 @@ private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_executor().context());
tcp_connection::create(io_context_);
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
@@ -97,6 +98,7 @@ private:
start_accept();
}
boost::asio::io_context& io_context_;
tcp::acceptor acceptor_;
};

View File

@@ -2,7 +2,7 @@
// client.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)

View File

@@ -2,7 +2,7 @@
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -35,7 +35,6 @@ int main()
{
boost::array<char, 1> recv_buf;
udp::endpoint remote_endpoint;
boost::system::error_code error;
socket.receive_from(boost::asio::buffer(recv_buf), remote_endpoint);
std::string message = make_daytime_string();

View File

@@ -2,7 +2,7 @@
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -12,7 +12,7 @@
#include <iostream>
#include <string>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/bind/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>

View File

@@ -2,7 +2,7 @@
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -12,7 +12,7 @@
#include <iostream>
#include <string>
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/bind/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
@@ -69,7 +69,8 @@ class tcp_server
{
public:
tcp_server(boost::asio::io_context& io_context)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
: io_context_(io_context),
acceptor_(io_context, tcp::endpoint(tcp::v4(), 13))
{
start_accept();
}
@@ -78,7 +79,7 @@ private:
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_executor().context());
tcp_connection::create(io_context_);
acceptor_.async_accept(new_connection->socket(),
boost::bind(&tcp_server::handle_accept, this, new_connection,
@@ -96,6 +97,7 @@ private:
start_accept();
}
boost::asio::io_context& io_context_;
tcp::acceptor acceptor_;
};

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -23,10 +23,10 @@ so we need the user to specify the server.
\until }
All programs that use asio need to have at least one boost::asio::io_service
object.
All programs that use asio need to have at least one I/O execution context,
such as an boost::asio::io_context object.
\until boost::asio::io_service
\until boost::asio::io_context
We need to turn the server name that was specified as a parameter to the
application, into a TCP endpoint. To do this we use an
@@ -34,17 +34,15 @@ boost::asio::ip::tcp::resolver object.
\until tcp::resolver
A resolver takes a query object and turns it into a list of endpoints. We
construct a query using the name of the server, specified in <tt>argv[1]</tt>,
and the name of the service, in this case <tt>"daytime"</tt>.
A resolver takes a host name and service name and turns them into a list of
endpoints. We perform a resolve call using the name of the server, specified in
<tt>argv[1]</tt>, and the name of the service, in this case <tt>"daytime"</tt>.
\until tcp::resolver::query
The list of endpoints is returned using an object of type
boost::asio::ip::tcp::resolver::results_type. This object is a range, with begin() and
end() member functions that may be used for iterating over the results.
The list of endpoints is returned using an iterator of type
boost::asio::ip::tcp::resolver::iterator. (Note that a default constructed
boost::asio::ip::tcp::resolver::iterator object can be used as an end iterator.)
\until tcp::resolver::iterator
\until resolver.resolve
Now we create and connect the socket. The list of endpoints obtained above may
contain both IPv4 and IPv6 endpoints, so we need to try each of them until we
@@ -101,7 +99,7 @@ We define the function <tt>make_daytime_string()</tt> to create the string to
be sent back to the client. This function will be reused in all of our daytime
server applications.
\until boost::asio::io_service
\until boost::asio::io_context
A boost::asio::ip::tcp::acceptor object needs to be created to listen
for new connections. It is initialised to listen on TCP port 13, for IP version 4.
@@ -149,12 +147,12 @@ Return to \ref tutdaytime2
\until {
We need to create a server object to accept incoming client connections. The
boost::asio::io_service object provides I/O services, such as sockets, that the
boost::asio::io_context object provides I/O services, such as sockets, that the
server object will use.
\until tcp_server
Run the boost::asio::io_service object so that it will perform asynchronous operations
Run the boost::asio::io_context object so that it will perform asynchronous operations
on your behalf.
\until return 0;
@@ -267,7 +265,7 @@ with UDP.
The start of the application is essentially the same as for the TCP daytime
client.
\until boost::asio::io_service
\until boost::asio::io_context
We use an boost::asio::ip::udp::resolver object to find the correct remote endpoint to
use based on the host and service names. The query is restricted to return only
@@ -279,8 +277,6 @@ The boost::asio::ip::udp::resolver::resolve() function is guaranteed to return a
least one endpoint in the list if it does not fail. This means it is safe to
dereference the return value directly.
\until udp::endpoint
Since UDP is datagram-oriented, we will not be using a stream socket. Create an
boost::asio::ip::udp::socket and initiate contact with the remote endpoint.
@@ -317,7 +313,7 @@ with UDP.
\dontinclude daytime5/server.cpp
\skip int main()
\until boost::asio::io_service
\until boost::asio::io_context
Create an boost::asio::ip::udp::socket object to receive requests on UDP port 13.
@@ -326,7 +322,7 @@ Create an boost::asio::ip::udp::socket object to receive requests on UDP port 13
Wait for a client to initiate contact with us. The remote_endpoint object will
be populated by boost::asio::ip::udp::socket::receive_from().
\until throw
\until receive_from
Determine what we are going to send back to the client.
@@ -366,7 +362,7 @@ Return to \ref tutdaytime5
\until {
Create a server object to accept incoming client requests, and run
the boost::asio::io_service object.
the boost::asio::io_context object.
\until return 0;
\until }
@@ -384,7 +380,7 @@ The constructor initialises a socket to listen on UDP port 13.
The function boost::asio::ip::udp::socket::async_receive_from() will cause the
application to listen in the background for a new request. When such a request
is received, the boost::asio::io_service object will invoke the
is received, the boost::asio::io_context object will invoke the
<tt>handle_receive()</tt> function with two arguments: a value of type
boost::system::error_code indicating whether the operation succeeded or failed, and a
<tt>size_t</tt> value <tt>bytes_transferred</tt> specifying the number of bytes
@@ -398,7 +394,7 @@ The function <tt>handle_receive()</tt> will service the client request.
The <tt>error</tt> parameter contains the result of the asynchronous operation.
Since we only provide the 1-byte <tt>recv_buffer_</tt> to contain the client's
request, the boost::asio::io_service object would return an error if the client sent
request, the boost::asio::io_context object would return an error if the client sent
anything larger. We can ignore such an error if it comes up.
\until {
@@ -456,7 +452,7 @@ have just written, into a single server application.
\dontinclude daytime7/server.cpp
\skip int main()
\until boost::asio::io_service
\until boost::asio::io_context
We will begin by creating a server object to accept a TCP client connection.
@@ -466,7 +462,7 @@ We also need a server object to accept a UDP client request.
\until udp_server
We have created two lots of work for the boost::asio::io_service object to do.
We have created two lots of work for the boost::asio::io_context object to do.
\until return 0;
\until }

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)

View File

@@ -2,7 +2,7 @@
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -10,13 +10,12 @@
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::asio::io_context io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
boost::asio::steady_timer t(io, boost::asio::chrono::seconds(5));
t.wait();
std::cout << "Hello, world!" << std::endl;

View File

@@ -2,7 +2,7 @@
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -10,7 +10,6 @@
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void print(const boost::system::error_code& /*e*/)
{
@@ -21,7 +20,7 @@ int main()
{
boost::asio::io_context io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
boost::asio::steady_timer t(io, boost::asio::chrono::seconds(5));
t.async_wait(&print);
io.run();

View File

@@ -2,7 +2,7 @@
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -10,18 +10,17 @@
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/bind/bind.hpp>
void print(const boost::system::error_code& /*e*/,
boost::asio::deadline_timer* t, int* count)
boost::asio::steady_timer* t, int* count)
{
if (*count < 5)
{
std::cout << *count << std::endl;
++(*count);
t->expires_at(t->expires_at() + boost::posix_time::seconds(1));
t->expires_at(t->expiry() + boost::asio::chrono::seconds(1));
t->async_wait(boost::bind(print,
boost::asio::placeholders::error, t, count));
}
@@ -32,7 +31,7 @@ int main()
boost::asio::io_context io;
int count = 0;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(1));
boost::asio::steady_timer t(io, boost::asio::chrono::seconds(1));
t.async_wait(boost::bind(print,
boost::asio::placeholders::error, &t, &count));

View File

@@ -2,7 +2,7 @@
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -10,14 +10,13 @@
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/bind/bind.hpp>
class printer
{
public:
printer(boost::asio::io_context& io)
: timer_(io, boost::posix_time::seconds(1)),
: timer_(io, boost::asio::chrono::seconds(1)),
count_(0)
{
timer_.async_wait(boost::bind(&printer::print, this));
@@ -35,13 +34,13 @@ public:
std::cout << count_ << std::endl;
++count_;
timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
timer_.expires_at(timer_.expiry() + boost::asio::chrono::seconds(1));
timer_.async_wait(boost::bind(&printer::print, this));
}
}
private:
boost::asio::deadline_timer timer_;
boost::asio::steady_timer timer_;
int count_;
};

View File

@@ -2,7 +2,7 @@
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -11,16 +11,15 @@
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/bind/bind.hpp>
class printer
{
public:
printer(boost::asio::io_context& io)
: strand_(io),
timer1_(io, boost::posix_time::seconds(1)),
timer2_(io, boost::posix_time::seconds(1)),
: strand_(boost::asio::make_strand(io)),
timer1_(io, boost::asio::chrono::seconds(1)),
timer2_(io, boost::asio::chrono::seconds(1)),
count_(0)
{
timer1_.async_wait(boost::asio::bind_executor(strand_,
@@ -42,7 +41,7 @@ public:
std::cout << "Timer 1: " << count_ << std::endl;
++count_;
timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));
timer1_.expires_at(timer1_.expiry() + boost::asio::chrono::seconds(1));
timer1_.async_wait(boost::asio::bind_executor(strand_,
boost::bind(&printer::print1, this)));
@@ -56,7 +55,7 @@ public:
std::cout << "Timer 2: " << count_ << std::endl;
++count_;
timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));
timer2_.expires_at(timer2_.expiry() + boost::asio::chrono::seconds(1));
timer2_.async_wait(boost::asio::bind_executor(strand_,
boost::bind(&printer::print2, this)));
@@ -64,9 +63,9 @@ public:
}
private:
boost::asio::io_context::strand strand_;
boost::asio::deadline_timer timer1_;
boost::asio::deadline_timer timer2_;
boost::asio::strand<boost::asio::io_context::executor_type> strand_;
boost::asio::steady_timer timer1_;
boost::asio::steady_timer timer2_;
int count_;
};

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2003-2021 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)
@@ -21,32 +21,28 @@ header file.
\until asio.hpp
Since this example uses timers, we need to include the appropriate
Boost.Date_Time header file for manipulating times.
All programs that use asio need to have at least one I/O execution context,
such as an boost::asio::io_context or boost::asio::thread_pool object. An I/O execution
context provides access to I/O functionality. We declare an object of type
boost::asio::io_context first thing in the main function.
\until posix_time.hpp
\until boost::asio::io_context
All programs that use asio need to have at least one boost::asio::io_service object.
This class provides access to I/O functionality. We declare an object of this
type first thing in the main function.
\until boost::asio::io_service
Next we declare an object of type boost::asio::deadline_timer. The core asio classes
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_service as their first constructor argument. The
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.
\until boost::asio::deadline_timer
\until boost::asio::steady_timer
In this simple example we perform a blocking wait on the timer.
That is, the call to boost::asio::deadline_timer::wait() will not return until the
That is, the call to boost::asio::steady_timer::wait() will not return until the
timer has expired, 5 seconds after it was created (i.e. <b>not</b> from when the
wait starts).
A deadline timer is always in one of two states: "expired" or "not expired". If
the boost::asio::deadline_timer::wait() function is called on an expired timer, it
will return immediately.
A timer is always in one of two states: "expired" or "not expired". If the
boost::asio::steady_timer::wait() function is called on an expired timer, it will
return immediately.
\until wait
@@ -77,39 +73,39 @@ asynchronous wait on the timer.
\dontinclude timer2/timer.cpp
\skip #include
\until posix_time.hpp
\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.
\until boost::asio::deadline_timer
\until boost::asio::steady_timer
Next, instead of doing a blocking wait as in tutorial Timer.1,
we call the boost::asio::deadline_timer::async_wait() function to perform an
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.
\skipline async_wait
Finally, we must call the boost::asio::io_service::run() member function
on the io_service object.
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>
be called from threads that are currently calling boost::asio::io_service::run().
Therefore unless the boost::asio::io_service::run() function is called the callback for
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.
The boost::asio::io_service::run() function will also continue to run while there is
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.
It is important to remember to give the io_service some work to do before
calling boost::asio::io_service::run(). For example, if we had omitted the above call
to boost::asio::deadline_timer::async_wait(), the io_service would not have had any
work to do, and consequently boost::asio::io_service::run() would have 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
to boost::asio::steady_timer::async_wait(), the io_context would not have had any
work to do, and consequently boost::asio::io_context::run() would have returned
immediately.
\skip run
@@ -138,7 +134,7 @@ your handler function.
\dontinclude timer3/timer.cpp
\skip #include
\until posix_time.hpp
\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
@@ -155,10 +151,10 @@ sixth time.
As mentioned above, this tutorial program uses a counter to
stop running when the timer fires for the sixth time. However you will observe
that there is no explicit call to ask the io_service to stop. Recall that in
tutorial Timer.2 we learnt that the boost::asio::io_service::run() function completes
that there is no explicit call to ask the io_context to stop. Recall that in
tutorial Timer.2 we learnt that the boost::asio::io_context::run() function completes
when there is no more "work" to do. By not starting a new asynchronous wait on
the timer when <tt>count</tt> reaches 5, the io_service will run out of work and
the timer when <tt>count</tt> reaches 5, the io_context will run out of work and
stop running.
\until ++
@@ -172,7 +168,7 @@ whole-second mark due to any delays in processing the handler.
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::deadline_timer::async_wait() function
with your callback 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
@@ -188,15 +184,15 @@ 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.
\until boost::asio::io_service
\until boost::asio::io_context
A new <tt>count</tt> variable is added so that we can stop the
program when the timer fires for the sixth time.
\until boost::asio::deadline_timer
\until boost::asio::steady_timer
As in Step 4, when making the call to
boost::asio::deadline_timer::async_wait() from <tt>main</tt> we bind the additional
boost::asio::steady_timer::async_wait() from <tt>main</tt> we bind the additional
parameters needed for the <tt>print</tt> function.
\until run
@@ -230,7 +226,7 @@ tutorial Timer.3.
\dontinclude timer4/timer.cpp
\skip #include
\until posix_time.hpp
\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
@@ -239,7 +235,7 @@ class called <tt>printer</tt>.
\until public
The constructor of this class will take a reference to the
io_service object and use it when initialising the <tt>timer_</tt> member. The
io_context object and use it when initialising the <tt>timer_</tt> member. The
counter used to shut down the program is now also a member of the class.
\until {
@@ -271,7 +267,7 @@ parameters.
\until };
The <tt>main</tt> function is much simpler than before, as it
now declares a local <tt>printer</tt> object before running the io_service as
now declares a local <tt>printer</tt> object before running the io_context as
normal.
\until }
@@ -292,14 +288,14 @@ Return to \ref tuttimer4
/**
\page tuttimer5 Timer.5 - Synchronising handlers in multithreaded programs
This tutorial demonstrates the use of the boost::asio::io_service::strand class to
This tutorial demonstrates the use of the boost::asio::strand class template to
synchronise callback handlers in a multithreaded program.
The previous four tutorials avoided the issue of handler synchronisation by
calling the boost::asio::io_service::run() function from one thread only. As you
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
boost::asio::io_service::run(). Consequently, calling boost::asio::io_service::run() from
boost::asio::io_context::run(). Consequently, calling boost::asio::io_context::run() from
only one thread ensures that callback handlers cannot run concurrently.
The single threaded approach is usually the best place to start when
@@ -312,14 +308,14 @@ on programs, particularly servers, including:
</ul>
If you find yourself running into these limitations, an alternative approach
is to have a pool of threads calling boost::asio::io_service::run(). However, as this
is to have a pool of threads calling boost::asio::io_context::run(). However, as this
allows handlers to execute concurrently, we need a method of synchronisation
when handlers might be accessing a shared, thread-unsafe resource.
\dontinclude timer5/timer.cpp
\skip #include
\until posix_time.hpp
\until bind.hpp
We start by defining a class called <tt>printer</tt>, similar
to the class in the previous tutorial. This class will extend the previous
@@ -327,27 +323,27 @@ tutorial by running two timers in parallel.
\until public
In addition to initialising a pair of boost::asio::deadline_timer members, the
In addition to initialising a pair of boost::asio::steady_timer members, the
constructor initialises the <tt>strand_</tt> member, an object of type
boost::asio::io_service::strand.
boost::asio::strand<boost::asio::io_context::executor_type>.
An boost::asio::io_service::strand is an executor that guarantees that, for those
handlers that are dispatched through it, an executing handler will be allowed
to complete before the next one is started. This is guaranteed irrespective of
the number of threads that are calling boost::asio::io_service::run(). Of course, the
handlers may still execute concurrently with other handlers that were
<b>not</b> dispatched through an boost::asio::io_service::strand, or were dispatched
through a different boost::asio::io_service::strand object.
The boost::asio::strand class template is an executor adapter that guarantees
that, for those handlers that are dispatched through it, an executing handler
will be allowed to complete before the next one is started. This is guaranteed
irrespective of the number of threads that are calling
boost::asio::io_context::run(). Of course, the handlers may still execute
concurrently with other handlers that were <b>not</b> dispatched through an
boost::asio::strand, or were dispatched through a different boost::asio::strand
object.
\until {
When initiating the asynchronous operations, each callback handler is "bound"
to an boost::asio::io_service::strand object. The
boost::asio::io_service::strand::bind_executor() function returns a new handler that
automatically dispatches its contained handler through the
boost::asio::io_service::strand object. By binding the handlers to the same
boost::asio::io_service::strand, we are ensuring that they cannot execute
concurrently.
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
binding the handlers to the same boost::asio::strand, we are ensuring that they
cannot execute concurrently.
\until }
\until }
@@ -359,12 +355,12 @@ tutorial, the shared resources used by the handlers (<tt>print1</tt> and
\until };
The <tt>main</tt> function now causes boost::asio::io_service::run() to
The <tt>main</tt> function now causes boost::asio::io_context::run() to
be called from two threads: the main thread and one additional thread. This is
accomplished using an boost::thread object.
Just as it would with a call from a single thread, concurrent calls to
boost::asio::io_service::run() will continue to execute while there is "work" left to
boost::asio::io_context::run() will continue to execute while there is "work" left to
do. The background thread will not exit until all asynchronous operations have
completed.