summaryrefslogtreecommitdiff
path: root/doc/html/boost_asio/example/cpp11
diff options
context:
space:
mode:
Diffstat (limited to 'doc/html/boost_asio/example/cpp11')
-rw-r--r--doc/html/boost_asio/example/cpp11/allocation/server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/buffers/reference_counted.cpp4
-rw-r--r--doc/html/boost_asio/example/cpp11/chat/chat_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/chat/chat_message.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/chat/chat_server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/echo/async_tcp_echo_server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/echo/async_udp_echo_server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/echo/blocking_tcp_echo_server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/echo/blocking_udp_echo_server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/fork/daemon.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/fork/process_per_connection.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/futures/daytime_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/handler_tracking/async_tcp_echo_server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/handler_tracking/custom_tracking.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/connection.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/connection.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/connection_manager.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/connection_manager.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/header.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/main.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/mime_types.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/mime_types.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/reply.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/reply.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/request.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/request_handler.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/request_handler.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/request_parser.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/request_parser.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/http/server/server.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/invocation/prioritised_handlers.cpp4
-rw-r--r--doc/html/boost_asio/example/cpp11/local/connect_pair.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/local/iostream_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/local/stream_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/local/stream_server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/multicast/receiver.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/multicast/sender.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/operations/composed_1.cpp3
-rw-r--r--doc/html/boost_asio/example/cpp11/operations/composed_2.cpp105
-rw-r--r--doc/html/boost_asio/example/cpp11/operations/composed_3.cpp152
-rw-r--r--doc/html/boost_asio/example/cpp11/operations/composed_4.cpp211
-rw-r--r--doc/html/boost_asio/example/cpp11/operations/composed_5.cpp302
-rw-r--r--doc/html/boost_asio/example/cpp11/operations/composed_6.cpp302
-rw-r--r--doc/html/boost_asio/example/cpp11/operations/composed_7.cpp222
-rw-r--r--doc/html/boost_asio/example/cpp11/operations/composed_8.cpp217
-rw-r--r--doc/html/boost_asio/example/cpp11/socks4/socks4.hpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/socks4/sync_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/spawn/echo_server.cpp15
-rw-r--r--doc/html/boost_asio/example/cpp11/spawn/parallel_grep.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/ssl/client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/ssl/server.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/timeouts/async_tcp_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/timeouts/blocking_tcp_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/timeouts/blocking_token_tcp_client.cpp14
-rw-r--r--doc/html/boost_asio/example/cpp11/timeouts/blocking_udp_client.cpp2
-rw-r--r--doc/html/boost_asio/example/cpp11/timeouts/server.cpp8
-rw-r--r--doc/html/boost_asio/example/cpp11/timers/time_t_timer.cpp2
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)