summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2024-04-22 08:04:58 +1000
committer Vas Crabb <vas@vastheman.com>2024-04-22 08:04:58 +1000
commit184292b730f4236bd4840e780fdad97ee060ec84 (patch)
tree67902161a465fe92aec78ca502de07092b8cde0f /3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp
parent24154bc1f00790f344120b3a85175d6f616c5ad0 (diff)
3rdparty/asio: Updated to 1.30.2
Diffstat (limited to '3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp')
-rw-r--r--3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp b/3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp
new file mode 100644
index 00000000000..3d5774c7421
--- /dev/null
+++ b/3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp
@@ -0,0 +1,152 @@
+//
+// callback_wrapper.cpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2024 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 <asio.hpp>
+#include <iostream>
+
+//------------------------------------------------------------------------------
+
+// This is a mock implementation of an API that uses a move-only function object
+// for exposing a callback. The callback has the signature void(std::string).
+
+template <typename Callback>
+void read_input(const std::string& prompt, Callback cb)
+{
+ std::thread(
+ [prompt, cb = std::move(cb)]() mutable
+ {
+ std::cout << prompt << ": ";
+ std::cout.flush();
+ std::string line;
+ std::getline(std::cin, line);
+ std::move(cb)(std::move(line));
+ }).detach();
+}
+
+//------------------------------------------------------------------------------
+
+// This is an asynchronous operation that wraps the callback-based API.
+
+// The initiating function for the asynchronous operation.
+template <typename CompletionToken>
+auto async_read_input(const std::string& prompt, CompletionToken&& token)
+{
+ // Define a function object that contains the code to launch the asynchronous
+ // operation. This is passed the concrete completion handler, followed by any
+ // additional arguments that were passed through the call to async_initiate.
+ auto init = [](auto handler, const std::string& prompt)
+ {
+ // According to the rules for asynchronous operations, we need to track
+ // outstanding work against the handler's associated executor until the
+ // asynchronous operation is complete.
+ auto work = asio::make_work_guard(handler);
+
+ // Launch the operation with a callback that will receive the result and
+ // pass it through to the asynchronous operation's completion handler.
+ read_input(prompt,
+ [
+ handler = std::move(handler),
+ work = std::move(work)
+ ](std::string result) mutable
+ {
+ // Get the handler's associated allocator. If the handler does not
+ // specify an allocator, use the recycling allocator as the default.
+ auto alloc = asio::get_associated_allocator(
+ handler, asio::recycling_allocator<void>());
+
+ // Dispatch the completion handler through the handler's associated
+ // executor, using the handler's associated allocator.
+ asio::dispatch(work.get_executor(),
+ asio::bind_allocator(alloc,
+ [
+ handler = std::move(handler),
+ result = std::string(result)
+ ]() mutable
+ {
+ std::move(handler)(result);
+ }));
+ });
+ };
+
+ // The async_initiate function is used to transform the supplied completion
+ // token to the completion handler. When calling this function we explicitly
+ // specify the completion signature of the operation. We must also return the
+ // result of the call since the completion token may produce a return value,
+ // such as a future.
+ return asio::async_initiate<CompletionToken, void(std::string)>(
+ init, // First, pass the function object that launches the operation,
+ token, // then the completion token that will be transformed to a handler,
+ prompt); // and, finally, any additional arguments to the function object.
+}
+
+//------------------------------------------------------------------------------
+
+void test_callback()
+{
+ asio::io_context io_context;
+
+ // Test our asynchronous operation using a lambda as a callback. We will use
+ // an io_context to specify an associated executor.
+ async_read_input("Enter your name",
+ asio::bind_executor(io_context,
+ [](const std::string& result)
+ {
+ std::cout << "Hello " << result << "\n";
+ }));
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+void test_deferred()
+{
+ asio::io_context io_context;
+
+ // Test our asynchronous operation using the deferred completion token. This
+ // token causes the operation's initiating function to package up the
+ // operation with its arguments to return a function object, which may then be
+ // used to launch the asynchronous operation.
+ auto op = async_read_input("Enter your name", asio::deferred);
+
+ // Launch our asynchronous operation using a lambda as a callback. We will use
+ // an io_context to obtain an associated executor.
+ std::move(op)(
+ asio::bind_executor(io_context,
+ [](const std::string& result)
+ {
+ std::cout << "Hello " << result << "\n";
+ }));
+
+ io_context.run();
+}
+
+//------------------------------------------------------------------------------
+
+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<std::string> f =
+ async_read_input("Enter your name", asio::use_future);
+
+ std::string result = f.get();
+ std::cout << "Hello " << result << "\n";
+}
+
+//------------------------------------------------------------------------------
+
+int main()
+{
+ test_callback();
+ test_deferred();
+ test_future();
+}