summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/src/doc/overview/strands.qbk
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/src/doc/overview/strands.qbk')
-rw-r--r--3rdparty/asio/src/doc/overview/strands.qbk85
1 files changed, 85 insertions, 0 deletions
diff --git a/3rdparty/asio/src/doc/overview/strands.qbk b/3rdparty/asio/src/doc/overview/strands.qbk
new file mode 100644
index 00000000000..0b6ff050dc6
--- /dev/null
+++ b/3rdparty/asio/src/doc/overview/strands.qbk
@@ -0,0 +1,85 @@
+[/
+ / Copyright (c) 2003-2016 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)
+ /]
+
+[section:strands Strands: Use Threads Without Explicit Locking]
+
+A strand is defined as a strictly sequential invocation of event handlers (i.e.
+no concurrent invocation). Use of strands allows execution of code in a
+multithreaded program without the need for explicit locking (e.g. using
+mutexes).
+
+Strands may be either implicit or explicit, as illustrated by the following
+alternative approaches:
+
+* Calling io_context::run() from only one thread means all event handlers
+ execute in an implicit strand, due to the io_context's guarantee that handlers
+ are only invoked from inside run().
+
+* Where there is a single chain of asynchronous operations associated with a
+ connection (e.g. in a half duplex protocol implementation like HTTP) there is
+ no possibility of concurrent execution of the handlers. This is an implicit
+ strand.
+
+* An explicit strand is an instance of `strand<>` or `io_context::strand`. All
+ event handler function objects need to be bound to the strand using
+ `asio::bind_executor()` or otherwise posted/dispatched through the strand
+ object.
+
+In the case of composed asynchronous operations, such as `async_read()` or
+`async_read_until()`, if a completion handler goes through a strand, then all
+intermediate handlers should also go through the same strand. This is needed to
+ensure thread safe access for any objects that are shared between the caller
+and the composed operation (in the case of `async_read()` it's the socket,
+which the caller can `close()` to cancel the operation).
+
+This is done by partially specialising the `asio::ssociated_executor<>` trait
+for all intermediate handlers. This trait forwards to the corresponding trait
+specialisation for the final handler:
+
+ struct my_handler
+ {
+ void operator()() { ... }
+ };
+
+ namespace asio {
+
+ template <class Executor>
+ struct associated_executor<my_handler, Executor>
+ {
+ // Custom implementation of Executor type requirements.
+ typedef my_executor type;
+
+ // Return a custom executor implementation.
+ static type get(const my_handler&, const Executor& = Executor())
+ {
+ return my_executor();
+ }
+ };
+
+ } // namespace asio
+
+The `asio::bind_executor()` function is a helper to bind a specific executor
+object, such as a strand, to a completion handler. This binding automatically
+specialises the `associated_executor` trait as shown above. For example, to
+bind a strand to a completion handler we would simply write:
+
+ my_socket.async_read_some(my_buffer,
+ asio::bind_executor(my_strand,
+ [](error_code ec, size_t length)
+ {
+ // ...
+ }));
+
+[heading See Also]
+
+[link asio.reference.bind_executor bind_executor],
+[link asio.reference.strand strand],
+[link asio.reference.io_context__strand io_context::strand],
+[link asio.tutorial.tuttimer5 tutorial Timer.5],
+[link asio.examples.cpp03_examples.http_server_3 HTTP server 3 example].
+
+[endsect]