diff options
Diffstat (limited to 'doc/html/boost_asio/example/cpp11')
60 files changed, 1200 insertions, 453 deletions
diff --git a/doc/html/boost_asio/example/cpp11/allocation/server.cpp b/doc/html/boost_asio/example/cpp11/allocation/server.cpp index fc1b03eaa3..c911ac1ff2 100644 --- a/doc/html/boost_asio/example/cpp11/allocation/server.cpp +++ b/doc/html/boost_asio/example/cpp11/allocation/server.cpp @@ -2,7 +2,7 @@ // server.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp b/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp index e56778f249..2d5685dce2 100644 --- a/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp +++ b/doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp @@ -2,7 +2,7 @@ // reference_counted.cpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) @@ -61,7 +61,7 @@ private: auto self(shared_from_this()); boost::asio::async_write(socket_, buffer, - [this, self](boost::system::error_code /*ec*/, std::size_t /*length*/) + [self](boost::system::error_code /*ec*/, std::size_t /*length*/) { }); } diff --git a/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp b/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp index 5ee9464cef..22319eaec4 100644 --- a/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp +++ b/doc/html/boost_asio/example/cpp11/chat/chat_client.cpp @@ -2,7 +2,7 @@ // chat_client.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/chat/chat_message.hpp b/doc/html/boost_asio/example/cpp11/chat/chat_message.hpp index 629105b05b..e2b6003746 100644 --- a/doc/html/boost_asio/example/cpp11/chat/chat_message.hpp +++ b/doc/html/boost_asio/example/cpp11/chat/chat_message.hpp @@ -2,7 +2,7 @@ // chat_message.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp b/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp index 6253ff2de9..164682eef4 100644 --- a/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp +++ b/doc/html/boost_asio/example/cpp11/chat/chat_server.cpp @@ -2,7 +2,7 @@ // chat_server.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp b/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp index 34fbb48808..76be908d01 100644 --- a/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp +++ b/doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp @@ -2,7 +2,7 @@ // async_tcp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/echo/async_udp_echo_server.cpp b/doc/html/boost_asio/example/cpp11/echo/async_udp_echo_server.cpp index d6e6587ee4..9e1fbe6d4a 100644 --- a/doc/html/boost_asio/example/cpp11/echo/async_udp_echo_server.cpp +++ b/doc/html/boost_asio/example/cpp11/echo/async_udp_echo_server.cpp @@ -2,7 +2,7 @@ // async_udp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp b/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp index fe6c447b39..ebc766f542 100644 --- a/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp +++ b/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp @@ -2,7 +2,7 @@ // blocking_tcp_echo_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp b/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp index c00a585242..b935f48ada 100644 --- a/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp +++ b/doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp @@ -2,7 +2,7 @@ // blocking_tcp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_client.cpp b/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_client.cpp index 887891a737..5381e83219 100644 --- a/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_client.cpp +++ b/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_client.cpp @@ -2,7 +2,7 @@ // blocking_udp_echo_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_server.cpp b/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_server.cpp index 0941b0c8d4..7c8050fbb0 100644 --- a/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_server.cpp +++ b/doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_server.cpp @@ -2,7 +2,7 @@ // blocking_udp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/fork/daemon.cpp b/doc/html/boost_asio/example/cpp11/fork/daemon.cpp index 2661926220..7968a80cc2 100644 --- a/doc/html/boost_asio/example/cpp11/fork/daemon.cpp +++ b/doc/html/boost_asio/example/cpp11/fork/daemon.cpp @@ -2,7 +2,7 @@ // daemon.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/fork/process_per_connection.cpp b/doc/html/boost_asio/example/cpp11/fork/process_per_connection.cpp index 3608c440da..a3b236d239 100644 --- a/doc/html/boost_asio/example/cpp11/fork/process_per_connection.cpp +++ b/doc/html/boost_asio/example/cpp11/fork/process_per_connection.cpp @@ -2,7 +2,7 @@ // process_per_connection.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp b/doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp index 1e49fc87d3..8b6a0bce8c 100644 --- a/doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp +++ b/doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp @@ -2,7 +2,7 @@ // daytime_client.cpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp b/doc/html/boost_asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp index 34fbb48808..76be908d01 100644 --- a/doc/html/boost_asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp +++ b/doc/html/boost_asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp @@ -2,7 +2,7 @@ // async_tcp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/handler_tracking/custom_tracking.hpp b/doc/html/boost_asio/example/cpp11/handler_tracking/custom_tracking.hpp index 997e1588c3..a63efc00bc 100644 --- a/doc/html/boost_asio/example/cpp11/handler_tracking/custom_tracking.hpp +++ b/doc/html/boost_asio/example/cpp11/handler_tracking/custom_tracking.hpp @@ -2,7 +2,7 @@ // custom_tracking.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/connection.cpp b/doc/html/boost_asio/example/cpp11/http/server/connection.cpp index 5eed24764e..8a2f1c7819 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/connection.cpp +++ b/doc/html/boost_asio/example/cpp11/http/server/connection.cpp @@ -2,7 +2,7 @@ // connection.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/connection.hpp b/doc/html/boost_asio/example/cpp11/http/server/connection.hpp index 5f3ce5c377..a97095ee1b 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/connection.hpp +++ b/doc/html/boost_asio/example/cpp11/http/server/connection.hpp @@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/connection_manager.cpp b/doc/html/boost_asio/example/cpp11/http/server/connection_manager.cpp index ac862994b5..bbb02465b2 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/connection_manager.cpp +++ b/doc/html/boost_asio/example/cpp11/http/server/connection_manager.cpp @@ -2,7 +2,7 @@ // connection_manager.cpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/connection_manager.hpp b/doc/html/boost_asio/example/cpp11/http/server/connection_manager.hpp index 027b9e92d8..aa47824507 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/connection_manager.hpp +++ b/doc/html/boost_asio/example/cpp11/http/server/connection_manager.hpp @@ -2,7 +2,7 @@ // connection_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/header.hpp b/doc/html/boost_asio/example/cpp11/http/server/header.hpp index 18bad986a4..067cc1f1fa 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/header.hpp +++ b/doc/html/boost_asio/example/cpp11/http/server/header.hpp @@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/main.cpp b/doc/html/boost_asio/example/cpp11/http/server/main.cpp index 15cffd5234..3661f06d34 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/main.cpp +++ b/doc/html/boost_asio/example/cpp11/http/server/main.cpp @@ -2,7 +2,7 @@ // main.cpp // ~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/mime_types.cpp b/doc/html/boost_asio/example/cpp11/http/server/mime_types.cpp index 0762cf7fea..c80ca9fcc7 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/mime_types.cpp +++ b/doc/html/boost_asio/example/cpp11/http/server/mime_types.cpp @@ -2,7 +2,7 @@ // mime_types.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/mime_types.hpp b/doc/html/boost_asio/example/cpp11/http/server/mime_types.hpp index a5f352e69a..950f84b73d 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/mime_types.hpp +++ b/doc/html/boost_asio/example/cpp11/http/server/mime_types.hpp @@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/reply.cpp b/doc/html/boost_asio/example/cpp11/http/server/reply.cpp index e1e23daaa6..c124e277a0 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/reply.cpp +++ b/doc/html/boost_asio/example/cpp11/http/server/reply.cpp @@ -2,7 +2,7 @@ // reply.cpp // ~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/reply.hpp b/doc/html/boost_asio/example/cpp11/http/server/reply.hpp index 03293227e7..8752c13802 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/reply.hpp +++ b/doc/html/boost_asio/example/cpp11/http/server/reply.hpp @@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/request.hpp b/doc/html/boost_asio/example/cpp11/http/server/request.hpp index 6488b1ddeb..1d0267bb60 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/request.hpp +++ b/doc/html/boost_asio/example/cpp11/http/server/request.hpp @@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/request_handler.cpp b/doc/html/boost_asio/example/cpp11/http/server/request_handler.cpp index 04a5959b12..45cbb64e15 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/request_handler.cpp +++ b/doc/html/boost_asio/example/cpp11/http/server/request_handler.cpp @@ -2,7 +2,7 @@ // request_handler.cpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/request_handler.hpp b/doc/html/boost_asio/example/cpp11/http/server/request_handler.hpp index 82bd61392a..8e240ccf4f 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/request_handler.hpp +++ b/doc/html/boost_asio/example/cpp11/http/server/request_handler.hpp @@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/request_parser.cpp b/doc/html/boost_asio/example/cpp11/http/server/request_parser.cpp index 4b148c5af6..5aa0a71a91 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/request_parser.cpp +++ b/doc/html/boost_asio/example/cpp11/http/server/request_parser.cpp @@ -2,7 +2,7 @@ // request_parser.cpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/request_parser.hpp b/doc/html/boost_asio/example/cpp11/http/server/request_parser.hpp index aaae6b9539..adc382a50a 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/request_parser.hpp +++ b/doc/html/boost_asio/example/cpp11/http/server/request_parser.hpp @@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/server.cpp b/doc/html/boost_asio/example/cpp11/http/server/server.cpp index ce415b80fd..50b6420289 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/server.cpp +++ b/doc/html/boost_asio/example/cpp11/http/server/server.cpp @@ -2,7 +2,7 @@ // server.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/http/server/server.hpp b/doc/html/boost_asio/example/cpp11/http/server/server.hpp index 820b46bc13..be05f49e19 100644 --- a/doc/html/boost_asio/example/cpp11/http/server/server.hpp +++ b/doc/html/boost_asio/example/cpp11/http/server/server.hpp @@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/invocation/prioritised_handlers.cpp b/doc/html/boost_asio/example/cpp11/invocation/prioritised_handlers.cpp index 101c97f02f..bd99fd049d 100644 --- a/doc/html/boost_asio/example/cpp11/invocation/prioritised_handlers.cpp +++ b/doc/html/boost_asio/example/cpp11/invocation/prioritised_handlers.cpp @@ -2,7 +2,7 @@ // prioritised_handlers.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) @@ -15,7 +15,7 @@ using boost::asio::ip::tcp; -class handler_priority_queue : boost::asio::execution_context +class handler_priority_queue : public boost::asio::execution_context { public: template <typename Function> diff --git a/doc/html/boost_asio/example/cpp11/local/connect_pair.cpp b/doc/html/boost_asio/example/cpp11/local/connect_pair.cpp index ad5428dd66..51c951f2c7 100644 --- a/doc/html/boost_asio/example/cpp11/local/connect_pair.cpp +++ b/doc/html/boost_asio/example/cpp11/local/connect_pair.cpp @@ -2,7 +2,7 @@ // connect_pair.cpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/local/iostream_client.cpp b/doc/html/boost_asio/example/cpp11/local/iostream_client.cpp index 7bab1d39fa..5afafa55eb 100644 --- a/doc/html/boost_asio/example/cpp11/local/iostream_client.cpp +++ b/doc/html/boost_asio/example/cpp11/local/iostream_client.cpp @@ -2,7 +2,7 @@ // stream_client.cpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/local/stream_client.cpp b/doc/html/boost_asio/example/cpp11/local/stream_client.cpp index 0faf617ea7..10cf81b8c5 100644 --- a/doc/html/boost_asio/example/cpp11/local/stream_client.cpp +++ b/doc/html/boost_asio/example/cpp11/local/stream_client.cpp @@ -2,7 +2,7 @@ // stream_client.cpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/local/stream_server.cpp b/doc/html/boost_asio/example/cpp11/local/stream_server.cpp index abfdf3d2fc..76eaa22bbe 100644 --- a/doc/html/boost_asio/example/cpp11/local/stream_server.cpp +++ b/doc/html/boost_asio/example/cpp11/local/stream_server.cpp @@ -2,7 +2,7 @@ // stream_server.cpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/multicast/receiver.cpp b/doc/html/boost_asio/example/cpp11/multicast/receiver.cpp index d785265b6c..daf49cc2bd 100644 --- a/doc/html/boost_asio/example/cpp11/multicast/receiver.cpp +++ b/doc/html/boost_asio/example/cpp11/multicast/receiver.cpp @@ -2,7 +2,7 @@ // receiver.cpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/multicast/sender.cpp b/doc/html/boost_asio/example/cpp11/multicast/sender.cpp index 7b52e4ebe3..3be381dcdf 100644 --- a/doc/html/boost_asio/example/cpp11/multicast/sender.cpp +++ b/doc/html/boost_asio/example/cpp11/multicast/sender.cpp @@ -2,7 +2,7 @@ // sender.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/operations/composed_1.cpp b/doc/html/boost_asio/example/cpp11/operations/composed_1.cpp index c2aa084455..84e3001bcf 100644 --- a/doc/html/boost_asio/example/cpp11/operations/composed_1.cpp +++ b/doc/html/boost_asio/example/cpp11/operations/composed_1.cpp @@ -2,7 +2,7 @@ // composed_1.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) @@ -26,6 +26,7 @@ using boost::asio::ip::tcp; // simply repackage an existing operation. The asynchronous operation // requirements are met by delegating responsibility to the underlying // operation. + template <typename CompletionToken> auto async_write_message(tcp::socket& socket, const char* message, CompletionToken&& token) diff --git a/doc/html/boost_asio/example/cpp11/operations/composed_2.cpp b/doc/html/boost_asio/example/cpp11/operations/composed_2.cpp index d03fece9d5..d214d164fb 100644 --- a/doc/html/boost_asio/example/cpp11/operations/composed_2.cpp +++ b/doc/html/boost_asio/example/cpp11/operations/composed_2.cpp @@ -2,19 +2,17 @@ // composed_2.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) // -#include <boost/asio/bind_executor.hpp> #include <boost/asio/io_context.hpp> #include <boost/asio/ip/tcp.hpp> #include <boost/asio/use_future.hpp> #include <boost/asio/write.hpp> #include <cstring> -#include <functional> #include <iostream> #include <string> #include <type_traits> @@ -24,63 +22,49 @@ using boost::asio::ip::tcp; //------------------------------------------------------------------------------ -// In this composed operation we repackage an existing operation, but with a -// different completion handler signature. The asynchronous operation -// requirements are met by delegating responsibility to the underlying -// operation. +// This next simplest example of a composed asynchronous operation involves +// repackaging multiple operations but choosing to invoke just one of them. All +// of these underlying operations have the same completion signature. The +// asynchronous operation requirements are met by delegating responsibility to +// the underlying operations. + template <typename CompletionToken> auto async_write_message(tcp::socket& socket, - const char* message, CompletionToken&& token) + const char* message, bool allow_partial_write, + CompletionToken&& token) // The return type of the initiating function is deduced from the combination // of CompletionToken type and the completion handler's signature. When the - // completion token is a simple callback, the return type is always void. - // In this example, when the completion token is boost::asio::yield_context - // (used for stackful coroutines) the return type would be also be void, as - // there is no non-error argument to the completion handler. When the - // completion token is boost::asio::use_future it would be std::future<void>. + // completion token is a simple callback, the return type is void. However, + // when the completion token is boost::asio::yield_context (used for stackful + // coroutines) the return type would be std::size_t, and when the completion + // token is boost::asio::use_future it would be std::future<std::size_t>. -> typename boost::asio::async_result< typename std::decay<CompletionToken>::type, - void(boost::system::error_code)>::return_type + void(boost::system::error_code, std::size_t)>::return_type { - // The boost::asio::async_completion object takes the completion token and - // from it creates: - // - // - completion.completion_handler: - // A completion handler (i.e. a callback) with the specified signature. - // - // - completion.result: - // An object from which we obtain the result of the initiating function. - boost::asio::async_completion<CompletionToken, - void(boost::system::error_code)> completion(token); - - // The async_write operation has a completion handler signature of: - // - // void(boost::system::error_code error, std::size n) - // - // This differs from our operation's signature in that it is also passed the - // number of bytes transferred as an argument of type std::size_t. We will - // adapt our completion handler to this signature by using std::bind, which - // drops the additional argument. - // - // However, it is essential to the correctness of our composed operation that - // we preserve the executor of the user-supplied completion handler. The - // std::bind function will not do this for us, so we must do this by first - // obtaining the completion handler's associated executor (defaulting to the - // I/O executor - in this case the executor of the socket - if the completion - // handler does not have its own) ... - auto executor = boost::asio::get_associated_executor( - completion.completion_handler, socket.get_executor()); - - // ... and then binding this executor to our adapted completion handler using - // the boost::asio::bind_executor function. - boost::asio::async_write(socket, - boost::asio::buffer(message, std::strlen(message)), - boost::asio::bind_executor(executor, - std::bind(std::move(completion.completion_handler), - std::placeholders::_1))); - - // Finally, we return the result of the initiating function. - return completion.result.get(); + // As the return type of the initiating function is deduced solely from the + // CompletionToken and completion signature, we know that two different + // asynchronous operations having the same completion signature will produce + // the same return type, when passed the same CompletionToken. This allows us + // to trivially delegate to alternate implementations. + if (allow_partial_write) + { + // When delegating to an underlying operation we must take care to + // perfectly forward the completion token. This ensures that our operation + // works correctly with move-only function objects as callbacks, as well as + // other completion token types. + return socket.async_write_some( + boost::asio::buffer(message, std::strlen(message)), + std::forward<CompletionToken>(token)); + } + else + { + // As above, we must perfectly forward the completion token when calling + // the alternate underlying operation. + return boost::asio::async_write(socket, + boost::asio::buffer(message, std::strlen(message)), + std::forward<CompletionToken>(token)); + } } //------------------------------------------------------------------------------ @@ -93,12 +77,12 @@ void test_callback() tcp::socket socket = acceptor.accept(); // Test our asynchronous operation using a lambda as a callback. - async_write_message(socket, "Testing callback\r\n", - [](const boost::system::error_code& error) + async_write_message(socket, "Testing callback\r\n", false, + [](const boost::system::error_code& error, std::size_t n) { if (!error) { - std::cout << "Message sent\n"; + std::cout << n << " bytes transferred\n"; } else { @@ -121,17 +105,16 @@ void test_future() // Test our asynchronous operation using the use_future completion token. // This token causes the operation's initiating function to return a future, // which may be used to synchronously wait for the result of the operation. - std::future<void> f = async_write_message( - socket, "Testing future\r\n", boost::asio::use_future); + std::future<std::size_t> f = async_write_message( + socket, "Testing future\r\n", false, boost::asio::use_future); io_context.run(); - // Get the result of the operation. try { // Get the result of the operation. - f.get(); - std::cout << "Message sent\n"; + std::size_t n = f.get(); + std::cout << n << " bytes transferred\n"; } catch (const std::exception& e) { diff --git a/doc/html/boost_asio/example/cpp11/operations/composed_3.cpp b/doc/html/boost_asio/example/cpp11/operations/composed_3.cpp index 67f669ec73..e6ea81915d 100644 --- a/doc/html/boost_asio/example/cpp11/operations/composed_3.cpp +++ b/doc/html/boost_asio/example/cpp11/operations/composed_3.cpp @@ -2,7 +2,7 @@ // composed_3.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) @@ -22,13 +22,76 @@ using boost::asio::ip::tcp; +// NOTE: This example requires the new boost::asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + //------------------------------------------------------------------------------ // In this composed operation we repackage an existing operation, but with a -// different completion handler signature. We will also intercept an empty -// message as an invalid argument, and propagate the corresponding error to the -// user. The asynchronous operation requirements are met by delegating -// responsibility to the underlying operation. +// different completion handler signature. The asynchronous operation +// requirements are met by delegating responsibility to the underlying +// operation. + +// In addition to determining the mechanism by which an asynchronous operation +// delivers its result, a completion token also determines the time when the +// operation commences. For example, when the completion token is a simple +// callback the operation commences before the initiating function returns. +// However, if the completion token's delivery mechanism uses a future, we +// might instead want to defer initiation of the operation until the returned +// future object is waited upon. +// +// To enable this, when implementing an asynchronous operation we must package +// the initiation step as a function object. +struct async_write_message_initiation +{ + // The initiation function object's call operator is passed the concrete + // completion handler produced by the completion token. This completion + // handler matches the asynchronous operation's completion handler signature, + // which in this example is: + // + // void(boost::system::error_code error) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments as members in the initiaton function object. However, we should + // prefer to propagate them as function call arguments as this allows the + // completion token to optimise how they are passed. For example, a lazy + // future which defers initiation would need to make a decay-copy of the + // arguments, but when using a simple callback the arguments can be trivially + // forwarded straight through.) + template <typename CompletionHandler> + void operator()(CompletionHandler&& completion_handler, + tcp::socket& socket, const char* message) const + { + // The async_write operation has a completion handler signature of: + // + // void(boost::system::error_code error, std::size n) + // + // This differs from our operation's signature in that it is also passed + // the number of bytes transferred as an argument of type std::size_t. We + // will adapt our completion handler to async_write's completion handler + // signature by using std::bind, which drops the additional argument. + // + // However, it is essential to the correctness of our composed operation + // that we preserve the executor of the user-supplied completion handler. + // The std::bind function will not do this for us, so we must do this by + // first obtaining the completion handler's associated executor (defaulting + // to the I/O executor - in this case the executor of the socket - if the + // completion handler does not have its own) ... + auto executor = boost::asio::get_associated_executor( + completion_handler, socket.get_executor()); + + // ... and then binding this executor to our adapted completion handler + // using the boost::asio::bind_executor function. + boost::asio::async_write(socket, + boost::asio::buffer(message, std::strlen(message)), + boost::asio::bind_executor(executor, + std::bind(std::forward<CompletionHandler>( + completion_handler), std::placeholders::_1))); + } +}; + template <typename CompletionToken> auto async_write_message(tcp::socket& socket, const char* message, CompletionToken&& token) @@ -43,65 +106,25 @@ auto async_write_message(tcp::socket& socket, typename std::decay<CompletionToken>::type, void(boost::system::error_code)>::return_type { - // The boost::asio::async_completion object takes the completion token and - // from it creates: - // - // - completion.completion_handler: - // A completion handler (i.e. a callback) with the specified signature. - // - // - completion.result: - // An object from which we obtain the result of the initiating function. - boost::asio::async_completion<CompletionToken, - void(boost::system::error_code)> completion(token); - - // If the user passes an empty message, this operation results in an - // invalid_argument error. This error is propagated to the user using the - // boost::asio::post operation. The async_write operation is used only for - // valid input. + // The boost::asio::async_initiate function takes: // - // The post operation has a completion handler signature of: + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. // - // void() + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. // - // and the async_write operation has a completion handler signature of: - // - // void(boost::system::error_code error, std::size n) - // - // Both of these operations' completion handler signatures differ from our - // operation's completion handler signature. We will adapt our completion - // handler to these signatures by using std::bind, which drops the additional - // arguments. - // - // However, it is essential to the correctness of our composed operation that - // we preserve the executor of the user-supplied completion handler. The - // std::bind function will not do this for us, so we must do this by first - // obtaining the completion handler's associated executor (defaulting to the - // I/O executor - in this case the executor of the socket - if the completion - // handler does not have its own) ... - auto executor = boost::asio::get_associated_executor( - completion.completion_handler, socket.get_executor()); - - // ... and then binding it to our adapted completion handlers using the - // boost::asio::bind_executor function. - std::size_t length = std::strlen(message); - if (length == 0) - { - boost::asio::post( - boost::asio::bind_executor(executor, - std::bind(std::move(completion.completion_handler), - boost::asio::error::invalid_argument))); - } - else - { - boost::asio::async_write(socket, - boost::asio::buffer(message, length), - boost::asio::bind_executor(executor, - std::bind(std::move(completion.completion_handler), - std::placeholders::_1))); - } - - // Finally, we return the result of the initiating function. - return completion.result.get(); + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return boost::asio::async_initiate< + CompletionToken, void(boost::system::error_code)>( + async_write_message_initiation(), + token, std::ref(socket), message); } //------------------------------------------------------------------------------ @@ -114,7 +137,7 @@ void test_callback() tcp::socket socket = acceptor.accept(); // Test our asynchronous operation using a lambda as a callback. - async_write_message(socket, "", + async_write_message(socket, "Testing callback\r\n", [](const boost::system::error_code& error) { if (!error) @@ -143,10 +166,11 @@ void test_future() // This token causes the operation's initiating function to return a future, // which may be used to synchronously wait for the result of the operation. std::future<void> f = async_write_message( - socket, "", boost::asio::use_future); + socket, "Testing future\r\n", boost::asio::use_future); io_context.run(); + // Get the result of the operation. try { // Get the result of the operation. @@ -155,7 +179,7 @@ void test_future() } catch (const std::exception& e) { - std::cout << "Exception: " << e.what() << "\n"; + std::cout << "Error: " << e.what() << "\n"; } } diff --git a/doc/html/boost_asio/example/cpp11/operations/composed_4.cpp b/doc/html/boost_asio/example/cpp11/operations/composed_4.cpp index 38055a1662..f14a3ceb6e 100644 --- a/doc/html/boost_asio/example/cpp11/operations/composed_4.cpp +++ b/doc/html/boost_asio/example/cpp11/operations/composed_4.cpp @@ -2,35 +2,115 @@ // composed_4.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) // +#include <boost/asio/bind_executor.hpp> #include <boost/asio/io_context.hpp> #include <boost/asio/ip/tcp.hpp> #include <boost/asio/use_future.hpp> #include <boost/asio/write.hpp> +#include <cstring> #include <functional> #include <iostream> -#include <memory> -#include <sstream> #include <string> #include <type_traits> #include <utility> using boost::asio::ip::tcp; +// NOTE: This example requires the new boost::asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + //------------------------------------------------------------------------------ -// This composed operation automatically serialises a message, using its I/O -// streams insertion operator, before sending it on the socket. To do this, it -// must allocate a buffer for the encoded message and ensure this buffer's -// validity until the underlying async_write operation completes. -template <typename T, typename CompletionToken> +// In this composed operation we repackage an existing operation, but with a +// different completion handler signature. We will also intercept an empty +// message as an invalid argument, and propagate the corresponding error to the +// user. The asynchronous operation requirements are met by delegating +// responsibility to the underlying operation. + +// In addition to determining the mechanism by which an asynchronous operation +// delivers its result, a completion token also determines the time when the +// operation commences. For example, when the completion token is a simple +// callback the operation commences before the initiating function returns. +// However, if the completion token's delivery mechanism uses a future, we +// might instead want to defer initiation of the operation until the returned +// future object is waited upon. +// +// To enable this, when implementing an asynchronous operation we must package +// the initiation step as a function object. +struct async_write_message_initiation +{ + // The initiation function object's call operator is passed the concrete + // completion handler produced by the completion token. This completion + // handler matches the asynchronous operation's completion handler signature, + // which in this example is: + // + // void(boost::system::error_code error) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments as members in the initiaton function object. However, we should + // prefer to propagate them as function call arguments as this allows the + // completion token to optimise how they are passed. For example, a lazy + // future which defers initiation would need to make a decay-copy of the + // arguments, but when using a simple callback the arguments can be trivially + // forwarded straight through.) + template <typename CompletionHandler> + void operator()(CompletionHandler&& completion_handler, + tcp::socket& socket, const char* message) const + { + // The post operation has a completion handler signature of: + // + // void() + // + // and the async_write operation has a completion handler signature of: + // + // void(boost::system::error_code error, std::size n) + // + // Both of these operations' completion handler signatures differ from our + // operation's completion handler signature. We will adapt our completion + // handler to these signatures by using std::bind, which drops the + // additional arguments. + // + // However, it is essential to the correctness of our composed operation + // that we preserve the executor of the user-supplied completion handler. + // The std::bind function will not do this for us, so we must do this by + // first obtaining the completion handler's associated executor (defaulting + // to the I/O executor - in this case the executor of the socket - if the + // completion handler does not have its own) ... + auto executor = boost::asio::get_associated_executor( + completion_handler, socket.get_executor()); + + // ... and then binding this executor to our adapted completion handler + // using the boost::asio::bind_executor function. + std::size_t length = std::strlen(message); + if (length == 0) + { + boost::asio::post( + boost::asio::bind_executor(executor, + std::bind(std::forward<CompletionHandler>(completion_handler), + boost::asio::error::invalid_argument))); + } + else + { + boost::asio::async_write(socket, + boost::asio::buffer(message, length), + boost::asio::bind_executor(executor, + std::bind(std::forward<CompletionHandler>(completion_handler), + std::placeholders::_1))); + } + } +}; + +template <typename CompletionToken> auto async_write_message(tcp::socket& socket, - const T& message, CompletionToken&& token) + const char* message, CompletionToken&& token) // The return type of the initiating function is deduced from the combination // of CompletionToken type and the completion handler's signature. When the // completion token is a simple callback, the return type is always void. @@ -42,98 +122,25 @@ auto async_write_message(tcp::socket& socket, typename std::decay<CompletionToken>::type, void(boost::system::error_code)>::return_type { - // Define a type alias for the concrete completion handler, as we will use - // the type in several places in the implementation below. - using completion_handler_type = - typename boost::asio::async_completion<CompletionToken, - void(boost::system::error_code)>::completion_handler_type; - - // In this example, the composed operation's intermediate completion handler - // is implemented as a hand-crafted function object, rather than a lambda. - struct intermediate_completion_handler - { - // The intermediate completion handler holds a reference to the socket so - // that it can obtain the I/O executor (see get_executor below). - tcp::socket& socket_; - - // The allocated buffer for the encoded message. The std::unique_ptr smart - // pointer is move-only, and as a consequence our intermediate completion - // handler is also move-only. - std::unique_ptr<std::string> encoded_message_; - - // The user-supplied completion handler. - completion_handler_type handler_; - - // The function call operator matches the completion signature of the - // async_write operation. - void operator()(const boost::system::error_code& error, std::size_t /*n*/) - { - // Deallocate the encoded message before calling the user-supplied - // completion handler. - encoded_message_.reset(); - - // Call the user-supplied handler with the result of the operation. - // The arguments must match the completion signature of our composed - // operation. - handler_(error); - } - - // It is essential to the correctness of our composed operation that we - // preserve the executor of the user-supplied completion handler. With a - // hand-crafted function object we can do this by defining a nested type - // executor_type and member function get_executor. These obtain the - // completion handler's associated executor, and default to the I/O - // executor - in this case the executor of the socket - if the completion - // handler does not have its own. - using executor_type = boost::asio::associated_executor_t< - completion_handler_type, tcp::socket::executor_type>; - - executor_type get_executor() const noexcept - { - return boost::asio::get_associated_executor( - handler_, socket_.get_executor()); - } - - // Although not necessary for correctness, we may also preserve the - // allocator of the user-supplied completion handler. This is achieved by - // defining a nested type allocator_type and member function get_allocator. - // These obtain the completion handler's associated allocator, and default - // to std::allocator<void> if the completion handler does not have its own. - using allocator_type = boost::asio::associated_allocator_t< - completion_handler_type, std::allocator<void>>; - - allocator_type get_allocator() const noexcept - { - return boost::asio::get_associated_allocator( - handler_, std::allocator<void>{}); - } - }; - - // The boost::asio::async_completion object takes the completion token and - // from it creates: + // The boost::asio::async_initiate function takes: + // + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. // - // - completion.completion_handler: - // A completion handler (i.e. a callback) with the specified signature. + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. // - // - completion.result: - // An object from which we obtain the result of the initiating function. - boost::asio::async_completion<CompletionToken, - void(boost::system::error_code)> completion(token); - - // Encode the message and copy it into an allocated buffer. The buffer will - // be maintained for the lifetime of the asynchronous operation. - std::ostringstream os; - os << message; - std::unique_ptr<std::string> encoded_message(new std::string(os.str())); - - // Initiate the underlying async_write operation using our intermediate - // completion handler. - boost::asio::async_write(socket, boost::asio::buffer(*encoded_message), - intermediate_completion_handler{socket, std::move(encoded_message), - std::move(completion.completion_handler)}); - - // Finally, we return the result of the initiating function. - return completion.result.get(); + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return boost::asio::async_initiate< + CompletionToken, void(boost::system::error_code)>( + async_write_message_initiation(), + token, std::ref(socket), message); } //------------------------------------------------------------------------------ @@ -146,7 +153,7 @@ void test_callback() tcp::socket socket = acceptor.accept(); // Test our asynchronous operation using a lambda as a callback. - async_write_message(socket, "Testing callback\r\n", + async_write_message(socket, "", [](const boost::system::error_code& error) { if (!error) @@ -175,7 +182,7 @@ void test_future() // This token causes the operation's initiating function to return a future, // which may be used to synchronously wait for the result of the operation. std::future<void> f = async_write_message( - socket, "Testing future\r\n", boost::asio::use_future); + socket, "", boost::asio::use_future); io_context.run(); @@ -187,7 +194,7 @@ void test_future() } catch (const std::exception& e) { - std::cout << "Error: " << e.what() << "\n"; + std::cout << "Exception: " << e.what() << "\n"; } } diff --git a/doc/html/boost_asio/example/cpp11/operations/composed_5.cpp b/doc/html/boost_asio/example/cpp11/operations/composed_5.cpp index 0d2a00ca17..a8e3dffe28 100644 --- a/doc/html/boost_asio/example/cpp11/operations/composed_5.cpp +++ b/doc/html/boost_asio/example/cpp11/operations/composed_5.cpp @@ -2,16 +2,14 @@ // composed_5.cpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) // -#include <boost/asio/executor_work_guard.hpp> #include <boost/asio/io_context.hpp> #include <boost/asio/ip/tcp.hpp> -#include <boost/asio/steady_timer.hpp> #include <boost/asio/use_future.hpp> #include <boost/asio/write.hpp> #include <functional> @@ -24,18 +22,125 @@ using boost::asio::ip::tcp; +// NOTE: This example requires the new boost::asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + //------------------------------------------------------------------------------ -// This composed operation shows composition of multiple underlying operations. -// It automatically serialises a message, using its I/O streams insertion -// operator, before sending it N times on the socket. To do this, it must -// allocate a buffer for the encoded message and ensure this buffer's validity -// until all underlying async_write operation complete. A one second delay is -// inserted prior to each write operation, using a steady_timer. +// This composed operation automatically serialises a message, using its I/O +// streams insertion operator, before sending it on the socket. To do this, it +// must allocate a buffer for the encoded message and ensure this buffer's +// validity until the underlying async_write operation completes. + +// In addition to determining the mechanism by which an asynchronous operation +// delivers its result, a completion token also determines the time when the +// operation commences. For example, when the completion token is a simple +// callback the operation commences before the initiating function returns. +// However, if the completion token's delivery mechanism uses a future, we +// might instead want to defer initiation of the operation until the returned +// future object is waited upon. +// +// To enable this, when implementing an asynchronous operation we must package +// the initiation step as a function object. +struct async_write_message_initiation +{ + // The initiation function object's call operator is passed the concrete + // completion handler produced by the completion token. This completion + // handler matches the asynchronous operation's completion handler signature, + // which in this example is: + // + // void(boost::system::error_code error) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments as members in the initiaton function object. However, we should + // prefer to propagate them as function call arguments as this allows the + // completion token to optimise how they are passed. For example, a lazy + // future which defers initiation would need to make a decay-copy of the + // arguments, but when using a simple callback the arguments can be trivially + // forwarded straight through.) + template <typename CompletionHandler> + void operator()(CompletionHandler&& completion_handler, + tcp::socket& socket, std::unique_ptr<std::string> encoded_message) const + { + // In this example, the composed operation's intermediate completion + // handler is implemented as a hand-crafted function object, rather than + // using a lambda or std::bind. + struct intermediate_completion_handler + { + // The intermediate completion handler holds a reference to the socket so + // that it can obtain the I/O executor (see get_executor below). + tcp::socket& socket_; + + // The allocated buffer for the encoded message. The std::unique_ptr + // smart pointer is move-only, and as a consequence our intermediate + // completion handler is also move-only. + std::unique_ptr<std::string> encoded_message_; + + // The user-supplied completion handler. + typename std::decay<CompletionHandler>::type handler_; + + // The function call operator matches the completion signature of the + // async_write operation. + void operator()(const boost::system::error_code& error, std::size_t /*n*/) + { + // Deallocate the encoded message before calling the user-supplied + // completion handler. + encoded_message_.reset(); + + // Call the user-supplied handler with the result of the operation. + // The arguments must match the completion signature of our composed + // operation. + handler_(error); + } + + // It is essential to the correctness of our composed operation that we + // preserve the executor of the user-supplied completion handler. With a + // hand-crafted function object we can do this by defining a nested type + // executor_type and member function get_executor. These obtain the + // completion handler's associated executor, and default to the I/O + // executor - in this case the executor of the socket - if the completion + // handler does not have its own. + using executor_type = boost::asio::associated_executor_t< + typename std::decay<CompletionHandler>::type, + tcp::socket::executor_type>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + handler_, socket_.get_executor()); + } + + // Although not necessary for correctness, we may also preserve the + // allocator of the user-supplied completion handler. This is achieved by + // defining a nested type allocator_type and member function + // get_allocator. These obtain the completion handler's associated + // allocator, and default to std::allocator<void> if the completion + // handler does not have its own. + using allocator_type = boost::asio::associated_allocator_t< + typename std::decay<CompletionHandler>::type, + std::allocator<void>>; + + allocator_type get_allocator() const noexcept + { + return boost::asio::get_associated_allocator( + handler_, std::allocator<void>{}); + } + }; + + // Initiate the underlying async_write operation using our intermediate + // completion handler. + auto encoded_message_buffer = boost::asio::buffer(*encoded_message); + boost::asio::async_write(socket, encoded_message_buffer, + intermediate_completion_handler{socket, std::move(encoded_message), + std::forward<CompletionHandler>(completion_handler)}); + } +}; + template <typename T, typename CompletionToken> -auto async_write_messages(tcp::socket& socket, - const T& message, std::size_t repeat_count, - CompletionToken&& token) +auto async_write_message(tcp::socket& socket, + const T& message, CompletionToken&& token) // The return type of the initiating function is deduced from the combination // of CompletionToken type and the completion handler's signature. When the // completion token is a simple callback, the return type is always void. @@ -47,152 +152,31 @@ auto async_write_messages(tcp::socket& socket, typename std::decay<CompletionToken>::type, void(boost::system::error_code)>::return_type { - // Define a type alias for the concrete completion handler, as we will use - // the type in several places in the implementation below. - using completion_handler_type = - typename boost::asio::async_completion<CompletionToken, - void(boost::system::error_code)>::completion_handler_type; - - // In this example, the composed operation's intermediate completion handler - // is implemented as a hand-crafted function object. - struct intermediate_completion_handler - { - // The intermediate completion handler holds a reference to the socket as - // it is used for multiple async_write operations, as well as for obtaining - // the I/O executor (see get_executor below). - tcp::socket& socket_; - - // The allocated buffer for the encoded message. The std::unique_ptr smart - // pointer is move-only, and as a consequence our intermediate completion - // handler is also move-only. - std::unique_ptr<std::string> encoded_message_; - - // The repeat count remaining. - std::size_t repeat_count_; - - // A steady timer used for introducing a delay. - std::unique_ptr<boost::asio::steady_timer> delay_timer_; - - // To manage the cycle between the multiple underlying asychronous - // operations, our intermediate completion handler is implemented as a - // state machine. - enum { starting, waiting, writing } state_; - - // As our composed operation performs multiple underlying I/O operations, - // we should maintain a work object against the I/O executor. This tells - // the I/O executor that there is still more work to come in the future. - boost::asio::executor_work_guard<tcp::socket::executor_type> io_work_; - - // The user-supplied completion handler, called once only on completion of - // the entire composed operation. - completion_handler_type handler_; - - // By having a default value for the second argument, this function call - // operator matches the completion signature of both the async_write and - // steady_timer::async_wait operations. - void operator()(const boost::system::error_code& error, std::size_t = 0) - { - if (!error) - { - switch (state_) - { - case starting: - case writing: - if (repeat_count_ > 0) - { - --repeat_count_; - state_ = waiting; - delay_timer_->expires_after(std::chrono::seconds(1)); - delay_timer_->async_wait(std::move(*this)); - return; // Composed operation not yet complete. - } - break; // Composed operation complete, continue below. - case waiting: - state_ = writing; - boost::asio::async_write(socket_, - boost::asio::buffer(*encoded_message_), std::move(*this)); - return; // Composed operation not yet complete. - } - } - - // This point is reached only on completion of the entire composed - // operation. - - // We no longer have any future work coming for the I/O executor. - io_work_.reset(); - - // Deallocate the encoded message before calling the user-supplied - // completion handler. - encoded_message_.reset(); - - // Call the user-supplied handler with the result of the operation. - handler_(error); - } - - // It is essential to the correctness of our composed operation that we - // preserve the executor of the user-supplied completion handler. With a - // hand-crafted function object we can do this by defining a nested type - // executor_type and member function get_executor. These obtain the - // completion handler's associated executor, and default to the I/O - // executor - in this case the executor of the socket - if the completion - // handler does not have its own. - using executor_type = boost::asio::associated_executor_t< - completion_handler_type, tcp::socket::executor_type>; - - executor_type get_executor() const noexcept - { - return boost::asio::get_associated_executor( - handler_, socket_.get_executor()); - } - - // Although not necessary for correctness, we may also preserve the - // allocator of the user-supplied completion handler. This is achieved by - // defining a nested type allocator_type and member function get_allocator. - // These obtain the completion handler's associated allocator, and default - // to std::allocator<void> if the completion handler does not have its own. - using allocator_type = boost::asio::associated_allocator_t< - completion_handler_type, std::allocator<void>>; - - allocator_type get_allocator() const noexcept - { - return boost::asio::get_associated_allocator( - handler_, std::allocator<void>{}); - } - }; - - // The boost::asio::async_completion object takes the completion token and - // from it creates: - // - // - completion.completion_handler: - // A completion handler (i.e. a callback) with the specified signature. - // - // - completion.result: - // An object from which we obtain the result of the initiating function. - boost::asio::async_completion<CompletionToken, - void(boost::system::error_code)> completion(token); - // Encode the message and copy it into an allocated buffer. The buffer will - // be maintained for the lifetime of the composed asynchronous operation. + // be maintained for the lifetime of the asynchronous operation. std::ostringstream os; os << message; std::unique_ptr<std::string> encoded_message(new std::string(os.str())); - // Create a steady_timer to be used for the delay between messages. - std::unique_ptr<boost::asio::steady_timer> delay_timer( - new boost::asio::steady_timer(socket.get_executor().context())); - - // Initiate the underlying operations by explicitly calling our intermediate - // completion handler's function call operator. - intermediate_completion_handler{ - socket, std::move(encoded_message), - repeat_count, std::move(delay_timer), - intermediate_completion_handler::starting, - boost::asio::make_work_guard(socket.get_executor()), - std::move(completion.completion_handler) - }({}); - - // Finally, we return the result of the initiating function. - return completion.result.get(); + // The boost::asio::async_initiate function takes: + // + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. + // + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. + // + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return boost::asio::async_initiate< + CompletionToken, void(boost::system::error_code)>( + async_write_message_initiation(), token, + std::ref(socket), std::move(encoded_message)); } //------------------------------------------------------------------------------ @@ -205,12 +189,12 @@ void test_callback() tcp::socket socket = acceptor.accept(); // Test our asynchronous operation using a lambda as a callback. - async_write_messages(socket, "Testing callback\r\n", 5, + async_write_message(socket, 123456, [](const boost::system::error_code& error) { if (!error) { - std::cout << "Messages sent\n"; + std::cout << "Message sent\n"; } else { @@ -233,8 +217,8 @@ void test_future() // Test our asynchronous operation using the use_future completion token. // This token causes the operation's initiating function to return a future, // which may be used to synchronously wait for the result of the operation. - std::future<void> f = async_write_messages( - socket, "Testing future\r\n", 5, boost::asio::use_future); + std::future<void> f = async_write_message( + socket, 654.321, boost::asio::use_future); io_context.run(); @@ -242,11 +226,11 @@ void test_future() { // Get the result of the operation. f.get(); - std::cout << "Messages sent\n"; + std::cout << "Message sent\n"; } catch (const std::exception& e) { - std::cout << "Error: " << e.what() << "\n"; + std::cout << "Exception: " << e.what() << "\n"; } } diff --git a/doc/html/boost_asio/example/cpp11/operations/composed_6.cpp b/doc/html/boost_asio/example/cpp11/operations/composed_6.cpp new file mode 100644 index 0000000000..7671839eb2 --- /dev/null +++ b/doc/html/boost_asio/example/cpp11/operations/composed_6.cpp @@ -0,0 +1,302 @@ +// +// composed_6.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 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) +// + +#include <boost/asio/executor_work_guard.hpp> +#include <boost/asio/io_context.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/steady_timer.hpp> +#include <boost/asio/use_future.hpp> +#include <boost/asio/write.hpp> +#include <functional> +#include <iostream> +#include <memory> +#include <sstream> +#include <string> +#include <type_traits> +#include <utility> + +using boost::asio::ip::tcp; + +// NOTE: This example requires the new boost::asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// This composed operation shows composition of multiple underlying operations. +// It automatically serialises a message, using its I/O streams insertion +// operator, before sending it N times on the socket. To do this, it must +// allocate a buffer for the encoded message and ensure this buffer's validity +// until all underlying async_write operation complete. A one second delay is +// inserted prior to each write operation, using a steady_timer. + +// In addition to determining the mechanism by which an asynchronous operation +// delivers its result, a completion token also determines the time when the +// operation commences. For example, when the completion token is a simple +// callback the operation commences before the initiating function returns. +// However, if the completion token's delivery mechanism uses a future, we +// might instead want to defer initiation of the operation until the returned +// future object is waited upon. +// +// To enable this, when implementing an asynchronous operation we must package +// the initiation step as a function object. +struct async_write_message_initiation +{ + // The initiation function object's call operator is passed the concrete + // completion handler produced by the completion token. This completion + // handler matches the asynchronous operation's completion handler signature, + // which in this example is: + // + // void(boost::system::error_code error) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments as members in the initiaton function object. However, we should + // prefer to propagate them as function call arguments as this allows the + // completion token to optimise how they are passed. For example, a lazy + // future which defers initiation would need to make a decay-copy of the + // arguments, but when using a simple callback the arguments can be trivially + // forwarded straight through.) + template <typename CompletionHandler> + void operator()(CompletionHandler&& completion_handler, tcp::socket& socket, + std::unique_ptr<std::string> encoded_message, std::size_t repeat_count, + std::unique_ptr<boost::asio::steady_timer> delay_timer) const + { + // In this example, the composed operation's intermediate completion + // handler is implemented as a hand-crafted function object. + struct intermediate_completion_handler + { + // The intermediate completion handler holds a reference to the socket as + // it is used for multiple async_write operations, as well as for + // obtaining the I/O executor (see get_executor below). + tcp::socket& socket_; + + // The allocated buffer for the encoded message. The std::unique_ptr + // smart pointer is move-only, and as a consequence our intermediate + // completion handler is also move-only. + std::unique_ptr<std::string> encoded_message_; + + // The repeat count remaining. + std::size_t repeat_count_; + + // A steady timer used for introducing a delay. + std::unique_ptr<boost::asio::steady_timer> delay_timer_; + + // To manage the cycle between the multiple underlying asychronous + // operations, our intermediate completion handler is implemented as a + // state machine. + enum { starting, waiting, writing } state_; + + // As our composed operation performs multiple underlying I/O operations, + // we should maintain a work object against the I/O executor. This tells + // the I/O executor that there is still more work to come in the future. + boost::asio::executor_work_guard<tcp::socket::executor_type> io_work_; + + // The user-supplied completion handler, called once only on completion + // of the entire composed operation. + typename std::decay<CompletionHandler>::type handler_; + + // By having a default value for the second argument, this function call + // operator matches the completion signature of both the async_write and + // steady_timer::async_wait operations. + void operator()(const boost::system::error_code& error, std::size_t = 0) + { + if (!error) + { + switch (state_) + { + case starting: + case writing: + if (repeat_count_ > 0) + { + --repeat_count_; + state_ = waiting; + delay_timer_->expires_after(std::chrono::seconds(1)); + delay_timer_->async_wait(std::move(*this)); + return; // Composed operation not yet complete. + } + break; // Composed operation complete, continue below. + case waiting: + state_ = writing; + boost::asio::async_write(socket_, + boost::asio::buffer(*encoded_message_), std::move(*this)); + return; // Composed operation not yet complete. + } + } + + // This point is reached only on completion of the entire composed + // operation. + + // We no longer have any future work coming for the I/O executor. + io_work_.reset(); + + // Deallocate the encoded message before calling the user-supplied + // completion handler. + encoded_message_.reset(); + + // Call the user-supplied handler with the result of the operation. + handler_(error); + } + + // It is essential to the correctness of our composed operation that we + // preserve the executor of the user-supplied completion handler. With a + // hand-crafted function object we can do this by defining a nested type + // executor_type and member function get_executor. These obtain the + // completion handler's associated executor, and default to the I/O + // executor - in this case the executor of the socket - if the completion + // handler does not have its own. + using executor_type = boost::asio::associated_executor_t< + typename std::decay<CompletionHandler>::type, + tcp::socket::executor_type>; + + executor_type get_executor() const noexcept + { + return boost::asio::get_associated_executor( + handler_, socket_.get_executor()); + } + + // Although not necessary for correctness, we may also preserve the + // allocator of the user-supplied completion handler. This is achieved by + // defining a nested type allocator_type and member function + // get_allocator. These obtain the completion handler's associated + // allocator, and default to std::allocator<void> if the completion + // handler does not have its own. + using allocator_type = boost::asio::associated_allocator_t< + typename std::decay<CompletionHandler>::type, + std::allocator<void>>; + + allocator_type get_allocator() const noexcept + { + return boost::asio::get_associated_allocator( + handler_, std::allocator<void>{}); + } + }; + + // Initiate the underlying async_write operation using our intermediate + // completion handler. + auto encoded_message_buffer = boost::asio::buffer(*encoded_message); + boost::asio::async_write(socket, encoded_message_buffer, + intermediate_completion_handler{ + socket, std::move(encoded_message), + repeat_count, std::move(delay_timer), + intermediate_completion_handler::starting, + boost::asio::make_work_guard(socket.get_executor()), + std::forward<CompletionHandler>(completion_handler)}); + } +}; + +template <typename T, typename CompletionToken> +auto async_write_messages(tcp::socket& socket, + const T& message, std::size_t repeat_count, + CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of CompletionToken type and the completion handler's signature. When the + // completion token is a simple callback, the return type is always void. + // In this example, when the completion token is boost::asio::yield_context + // (used for stackful coroutines) the return type would be also be void, as + // there is no non-error argument to the completion handler. When the + // completion token is boost::asio::use_future it would be std::future<void>. + -> typename boost::asio::async_result< + typename std::decay<CompletionToken>::type, + void(boost::system::error_code)>::return_type +{ + // Encode the message and copy it into an allocated buffer. The buffer will + // be maintained for the lifetime of the composed asynchronous operation. + std::ostringstream os; + os << message; + std::unique_ptr<std::string> encoded_message(new std::string(os.str())); + + // Create a steady_timer to be used for the delay between messages. + std::unique_ptr<boost::asio::steady_timer> delay_timer( + new boost::asio::steady_timer(socket.get_executor())); + + // The boost::asio::async_initiate function takes: + // + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. + // + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. + // + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return boost::asio::async_initiate< + CompletionToken, void(boost::system::error_code)>( + async_write_message_initiation(), token, std::ref(socket), + std::move(encoded_message), repeat_count, std::move(delay_timer)); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + boost::asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_messages(socket, "Testing callback\r\n", 5, + [](const boost::system::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + boost::asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<void> f = async_write_messages( + socket, "Testing future\r\n", 5, boost::asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + f.get(); + std::cout << "Messages sent\n"; + } + catch (const std::exception& e) + { + std::cout << "Error: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_future(); +} diff --git a/doc/html/boost_asio/example/cpp11/operations/composed_7.cpp b/doc/html/boost_asio/example/cpp11/operations/composed_7.cpp new file mode 100644 index 0000000000..8f9475ce8d --- /dev/null +++ b/doc/html/boost_asio/example/cpp11/operations/composed_7.cpp @@ -0,0 +1,222 @@ +// +// composed_7.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 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) +// + +#include <boost/asio/compose.hpp> +#include <boost/asio/io_context.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/steady_timer.hpp> +#include <boost/asio/use_future.hpp> +#include <boost/asio/write.hpp> +#include <functional> +#include <iostream> +#include <memory> +#include <sstream> +#include <string> +#include <type_traits> +#include <utility> + +using boost::asio::ip::tcp; + +// NOTE: This example requires the new boost::asio::async_compose function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// This composed operation shows composition of multiple underlying operations. +// It automatically serialises a message, using its I/O streams insertion +// operator, before sending it N times on the socket. To do this, it must +// allocate a buffer for the encoded message and ensure this buffer's validity +// until all underlying async_write operation complete. A one second delay is +// inserted prior to each write operation, using a steady_timer. + +// In this example, the composed operation's logic is implemented as a state +// machine within a hand-crafted function object. +struct async_write_messages_implementation +{ + // The implementation holds a reference to the socket as it is used for + // multiple async_write operations. + tcp::socket& socket_; + + // The allocated buffer for the encoded message. The std::unique_ptr smart + // pointer is move-only, and as a consequence our implementation is also + // move-only. + std::unique_ptr<std::string> encoded_message_; + + // The repeat count remaining. + std::size_t repeat_count_; + + // A steady timer used for introducing a delay. + std::unique_ptr<boost::asio::steady_timer> delay_timer_; + + // To manage the cycle between the multiple underlying asychronous + // operations, our implementation is a state machine. + enum { starting, waiting, writing } state_; + + // The first argument to our function object's call operator is a reference + // to the enclosing intermediate completion handler. This intermediate + // completion handler is provided for us by the boost::asio::async_compose + // function, and takes care of all the details required to implement a + // conforming asynchronous operation. When calling an underlying asynchronous + // operation, we pass it this enclosing intermediate completion handler + // as the completion token. + // + // All arguments after the first must be defaulted to allow the state machine + // to be started, as well as to allow the completion handler to match the + // completion signature of both the async_write and steady_timer::async_wait + // operations. + template <typename Self> + void operator()(Self& self, + const boost::system::error_code& error = boost::system::error_code(), + std::size_t = 0) + { + if (!error) + { + switch (state_) + { + case starting: + case writing: + if (repeat_count_ > 0) + { + --repeat_count_; + state_ = waiting; + delay_timer_->expires_after(std::chrono::seconds(1)); + delay_timer_->async_wait(std::move(self)); + return; // Composed operation not yet complete. + } + break; // Composed operation complete, continue below. + case waiting: + state_ = writing; + boost::asio::async_write(socket_, + boost::asio::buffer(*encoded_message_), std::move(self)); + return; // Composed operation not yet complete. + } + } + + // This point is reached only on completion of the entire composed + // operation. + + // Deallocate the encoded message and delay timer before calling the + // user-supplied completion handler. + encoded_message_.reset(); + delay_timer_.reset(); + + // Call the user-supplied handler with the result of the operation. + self.complete(error); + } +}; + +template <typename T, typename CompletionToken> +auto async_write_messages(tcp::socket& socket, + const T& message, std::size_t repeat_count, + CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of CompletionToken type and the completion handler's signature. When the + // completion token is a simple callback, the return type is always void. + // In this example, when the completion token is boost::asio::yield_context + // (used for stackful coroutines) the return type would be also be void, as + // there is no non-error argument to the completion handler. When the + // completion token is boost::asio::use_future it would be std::future<void>. + -> typename boost::asio::async_result< + typename std::decay<CompletionToken>::type, + void(boost::system::error_code)>::return_type +{ + // Encode the message and copy it into an allocated buffer. The buffer will + // be maintained for the lifetime of the composed asynchronous operation. + std::ostringstream os; + os << message; + std::unique_ptr<std::string> encoded_message(new std::string(os.str())); + + // Create a steady_timer to be used for the delay between messages. + std::unique_ptr<boost::asio::steady_timer> delay_timer( + new boost::asio::steady_timer(socket.get_executor())); + + // The boost::asio::async_compose function takes: + // + // - our asynchronous operation implementation, + // - the completion token, + // - the completion handler signature, and + // - any I/O objects (or executors) used by the operation + // + // It then wraps our implementation in an intermediate completion handler + // that meets the requirements of a conforming asynchronous operation. This + // includes tracking outstanding work against the I/O executors associated + // with the operation (in this example, this is the socket's executor). + return boost::asio::async_compose< + CompletionToken, void(boost::system::error_code)>( + async_write_messages_implementation{ + socket, std::move(encoded_message), + repeat_count, std::move(delay_timer), + async_write_messages_implementation::starting}, + token, socket); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + boost::asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_messages(socket, "Testing callback\r\n", 5, + [](const boost::system::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + boost::asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<void> f = async_write_messages( + socket, "Testing future\r\n", 5, boost::asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + f.get(); + std::cout << "Messages sent\n"; + } + catch (const std::exception& e) + { + std::cout << "Error: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_future(); +} diff --git a/doc/html/boost_asio/example/cpp11/operations/composed_8.cpp b/doc/html/boost_asio/example/cpp11/operations/composed_8.cpp new file mode 100644 index 0000000000..da0535457e --- /dev/null +++ b/doc/html/boost_asio/example/cpp11/operations/composed_8.cpp @@ -0,0 +1,217 @@ +// +// composed_8.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2019 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) +// + +#include <boost/asio/compose.hpp> +#include <boost/asio/io_context.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/steady_timer.hpp> +#include <boost/asio/use_future.hpp> +#include <boost/asio/write.hpp> +#include <functional> +#include <iostream> +#include <memory> +#include <sstream> +#include <string> +#include <type_traits> +#include <utility> + +using boost::asio::ip::tcp; + +// NOTE: This example requires the new boost::asio::async_compose function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// This composed operation shows composition of multiple underlying operations, +// using asio's stackless coroutines support to express the flow of control. It +// automatically serialises a message, using its I/O streams insertion +// operator, before sending it N times on the socket. To do this, it must +// allocate a buffer for the encoded message and ensure this buffer's validity +// until all underlying async_write operation complete. A one second delay is +// inserted prior to each write operation, using a steady_timer. + +#include <boost/asio/yield.hpp> + +// In this example, the composed operation's logic is implemented as a state +// machine within a hand-crafted function object. +struct async_write_messages_implementation +{ + // The implementation holds a reference to the socket as it is used for + // multiple async_write operations. + tcp::socket& socket_; + + // The allocated buffer for the encoded message. The std::unique_ptr smart + // pointer is move-only, and as a consequence our implementation is also + // move-only. + std::unique_ptr<std::string> encoded_message_; + + // The repeat count remaining. + std::size_t repeat_count_; + + // A steady timer used for introducing a delay. + std::unique_ptr<boost::asio::steady_timer> delay_timer_; + + // The coroutine state. + boost::asio::coroutine coro_; + + // The first argument to our function object's call operator is a reference + // to the enclosing intermediate completion handler. This intermediate + // completion handler is provided for us by the boost::asio::async_compose + // function, and takes care of all the details required to implement a + // conforming asynchronous operation. When calling an underlying asynchronous + // operation, we pass it this enclosing intermediate completion handler + // as the completion token. + // + // All arguments after the first must be defaulted to allow the state machine + // to be started, as well as to allow the completion handler to match the + // completion signature of both the async_write and steady_timer::async_wait + // operations. + template <typename Self> + void operator()(Self& self, + const boost::system::error_code& error = boost::system::error_code(), + std::size_t = 0) + { + reenter (coro_) + { + while (repeat_count_ > 0) + { + --repeat_count_; + + delay_timer_->expires_after(std::chrono::seconds(1)); + yield delay_timer_->async_wait(std::move(self)); + if (error) + break; + + yield boost::asio::async_write(socket_, + boost::asio::buffer(*encoded_message_), std::move(self)); + if (error) + break; + } + + // Deallocate the encoded message and delay timer before calling the + // user-supplied completion handler. + encoded_message_.reset(); + delay_timer_.reset(); + + // Call the user-supplied handler with the result of the operation. + self.complete(error); + } + } +}; + +#include <boost/asio/unyield.hpp> + +template <typename T, typename CompletionToken> +auto async_write_messages(tcp::socket& socket, + const T& message, std::size_t repeat_count, + CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of CompletionToken type and the completion handler's signature. When the + // completion token is a simple callback, the return type is always void. + // In this example, when the completion token is boost::asio::yield_context + // (used for stackful coroutines) the return type would be also be void, as + // there is no non-error argument to the completion handler. When the + // completion token is boost::asio::use_future it would be std::future<void>. + -> typename boost::asio::async_result< + typename std::decay<CompletionToken>::type, + void(boost::system::error_code)>::return_type +{ + // Encode the message and copy it into an allocated buffer. The buffer will + // be maintained for the lifetime of the composed asynchronous operation. + std::ostringstream os; + os << message; + std::unique_ptr<std::string> encoded_message(new std::string(os.str())); + + // Create a steady_timer to be used for the delay between messages. + std::unique_ptr<boost::asio::steady_timer> delay_timer( + new boost::asio::steady_timer(socket.get_executor())); + + // The boost::asio::async_compose function takes: + // + // - our asynchronous operation implementation, + // - the completion token, + // - the completion handler signature, and + // - any I/O objects (or executors) used by the operation + // + // It then wraps our implementation in an intermediate completion handler + // that meets the requirements of a conforming asynchronous operation. This + // includes tracking outstanding work against the I/O executors associated + // with the operation (in this example, this is the socket's executor). + return boost::asio::async_compose< + CompletionToken, void(boost::system::error_code)>( + async_write_messages_implementation{socket, + std::move(encoded_message), repeat_count, + std::move(delay_timer), boost::asio::coroutine()}, + token, socket); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + boost::asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_messages(socket, "Testing callback\r\n", 5, + [](const boost::system::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + boost::asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<void> f = async_write_messages( + socket, "Testing future\r\n", 5, boost::asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + f.get(); + std::cout << "Messages sent\n"; + } + catch (const std::exception& e) + { + std::cout << "Error: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_future(); +} diff --git a/doc/html/boost_asio/example/cpp11/socks4/socks4.hpp b/doc/html/boost_asio/example/cpp11/socks4/socks4.hpp index 90cca53a72..261c7ae050 100644 --- a/doc/html/boost_asio/example/cpp11/socks4/socks4.hpp +++ b/doc/html/boost_asio/example/cpp11/socks4/socks4.hpp @@ -2,7 +2,7 @@ // socks4.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/socks4/sync_client.cpp b/doc/html/boost_asio/example/cpp11/socks4/sync_client.cpp index 98f3153234..fad09e51f3 100644 --- a/doc/html/boost_asio/example/cpp11/socks4/sync_client.cpp +++ b/doc/html/boost_asio/example/cpp11/socks4/sync_client.cpp @@ -2,7 +2,7 @@ // sync_client.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp b/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp index 979c9a9273..b32d827aaa 100644 --- a/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp +++ b/doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp @@ -2,7 +2,7 @@ // echo_server.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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,10 +21,10 @@ using boost::asio::ip::tcp; class session : public std::enable_shared_from_this<session> { public: - explicit session(tcp::socket socket) + explicit session(boost::asio::io_context& io_context, tcp::socket socket) : socket_(std::move(socket)), - timer_(socket_.get_io_context()), - strand_(socket_.get_io_context()) + timer_(io_context), + strand_(io_context.get_executor()) { } @@ -67,7 +67,7 @@ public: private: tcp::socket socket_; boost::asio::steady_timer timer_; - boost::asio::io_context::strand strand_; + boost::asio::strand<boost::asio::io_context::executor_type> strand_; }; int main(int argc, char* argv[]) @@ -93,7 +93,10 @@ int main(int argc, char* argv[]) boost::system::error_code ec; tcp::socket socket(io_context); acceptor.async_accept(socket, yield[ec]); - if (!ec) std::make_shared<session>(std::move(socket))->go(); + if (!ec) + { + std::make_shared<session>(io_context, std::move(socket))->go(); + } } }); diff --git a/doc/html/boost_asio/example/cpp11/spawn/parallel_grep.cpp b/doc/html/boost_asio/example/cpp11/spawn/parallel_grep.cpp index e4af2624e7..899e90be25 100644 --- a/doc/html/boost_asio/example/cpp11/spawn/parallel_grep.cpp +++ b/doc/html/boost_asio/example/cpp11/spawn/parallel_grep.cpp @@ -2,7 +2,7 @@ // parallel_grep.cpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/ssl/client.cpp b/doc/html/boost_asio/example/cpp11/ssl/client.cpp index 038af71bb2..205198fa95 100644 --- a/doc/html/boost_asio/example/cpp11/ssl/client.cpp +++ b/doc/html/boost_asio/example/cpp11/ssl/client.cpp @@ -2,7 +2,7 @@ // client.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/ssl/server.cpp b/doc/html/boost_asio/example/cpp11/ssl/server.cpp index c97bea5b65..96860c0b29 100644 --- a/doc/html/boost_asio/example/cpp11/ssl/server.cpp +++ b/doc/html/boost_asio/example/cpp11/ssl/server.cpp @@ -2,7 +2,7 @@ // server.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/timeouts/async_tcp_client.cpp b/doc/html/boost_asio/example/cpp11/timeouts/async_tcp_client.cpp index cb7c9d1c19..38c495e04d 100644 --- a/doc/html/boost_asio/example/cpp11/timeouts/async_tcp_client.cpp +++ b/doc/html/boost_asio/example/cpp11/timeouts/async_tcp_client.cpp @@ -2,7 +2,7 @@ // async_tcp_client.cpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/timeouts/blocking_tcp_client.cpp b/doc/html/boost_asio/example/cpp11/timeouts/blocking_tcp_client.cpp index cf2638141b..b396259333 100644 --- a/doc/html/boost_asio/example/cpp11/timeouts/blocking_tcp_client.cpp +++ b/doc/html/boost_asio/example/cpp11/timeouts/blocking_tcp_client.cpp @@ -2,7 +2,7 @@ // blocking_tcp_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/timeouts/blocking_token_tcp_client.cpp b/doc/html/boost_asio/example/cpp11/timeouts/blocking_token_tcp_client.cpp index e13b0b1779..56c9fcfcfb 100644 --- a/doc/html/boost_asio/example/cpp11/timeouts/blocking_token_tcp_client.cpp +++ b/doc/html/boost_asio/example/cpp11/timeouts/blocking_token_tcp_client.cpp @@ -2,7 +2,7 @@ // blocking_token_tcp_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) @@ -22,13 +22,17 @@ using boost::asio::ip::tcp; +// We will use our sockets only with an io_context. +using tcp_socket = boost::asio::basic_stream_socket< + tcp, boost::asio::io_context::executor_type>; + //---------------------------------------------------------------------- // A custom completion token that makes asynchronous operations behave as // though they are blocking calls with a timeout. struct close_after { - close_after(std::chrono::steady_clock::duration t, tcp::socket& s) + close_after(std::chrono::steady_clock::duration t, tcp_socket& s) : timeout_(t), socket_(s) { } @@ -37,7 +41,7 @@ struct close_after std::chrono::steady_clock::duration timeout_; // The socket to be closed if the operation does not complete in time. - tcp::socket& socket_; + tcp_socket& socket_; }; namespace boost { @@ -125,7 +129,7 @@ public: private: std::chrono::steady_clock::duration timeout_; - tcp::socket& socket_; + tcp_socket& socket_; boost::system::error_code error_; T t_; }; @@ -150,7 +154,7 @@ int main(int argc, char* argv[]) // Resolve the host name and service to a list of endpoints. auto endpoints = tcp::resolver(io_context).resolve(argv[1], argv[2]); - tcp::socket socket(io_context); + tcp_socket socket(io_context); // Run an asynchronous connect operation with a timeout. boost::asio::async_connect(socket, endpoints, diff --git a/doc/html/boost_asio/example/cpp11/timeouts/blocking_udp_client.cpp b/doc/html/boost_asio/example/cpp11/timeouts/blocking_udp_client.cpp index 395ddd171a..7516976f55 100644 --- a/doc/html/boost_asio/example/cpp11/timeouts/blocking_udp_client.cpp +++ b/doc/html/boost_asio/example/cpp11/timeouts/blocking_udp_client.cpp @@ -2,7 +2,7 @@ // blocking_udp_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) diff --git a/doc/html/boost_asio/example/cpp11/timeouts/server.cpp b/doc/html/boost_asio/example/cpp11/timeouts/server.cpp index 94ae83efc3..699ad4741c 100644 --- a/doc/html/boost_asio/example/cpp11/timeouts/server.cpp +++ b/doc/html/boost_asio/example/cpp11/timeouts/server.cpp @@ -2,7 +2,7 @@ // server.cpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) @@ -329,10 +329,10 @@ private: channel& channel_; tcp::socket socket_; std::string input_buffer_; - steady_timer input_deadline_{socket_.get_executor().context()}; + steady_timer input_deadline_{socket_.get_executor()}; std::deque<std::string> output_queue_; - steady_timer non_empty_output_queue_{socket_.get_executor().context()}; - steady_timer output_deadline_{socket_.get_executor().context()}; + steady_timer non_empty_output_queue_{socket_.get_executor()}; + steady_timer output_deadline_{socket_.get_executor()}; }; typedef std::shared_ptr<tcp_session> tcp_session_ptr; diff --git a/doc/html/boost_asio/example/cpp11/timers/time_t_timer.cpp b/doc/html/boost_asio/example/cpp11/timers/time_t_timer.cpp index 0a9e66de67..ee8229a874 100644 --- a/doc/html/boost_asio/example/cpp11/timers/time_t_timer.cpp +++ b/doc/html/boost_asio/example/cpp11/timers/time_t_timer.cpp @@ -2,7 +2,7 @@ // time_t_timer.cpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2019 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) |