1[/ 2 / Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 3 / 4 / Distributed under the Boost Software License, Version 1.0. (See accompanying 5 / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 /] 7 8[section:strands Strands: Use Threads Without Explicit Locking] 9 10A strand is defined as a strictly sequential invocation of event handlers (i.e. 11no concurrent invocation). Use of strands allows execution of code in a 12multithreaded program without the need for explicit locking (e.g. using 13mutexes). 14 15Strands may be either implicit or explicit, as illustrated by the following 16alternative approaches: 17 18* Calling io_context::run() from only one thread means all event handlers 19 execute in an implicit strand, due to the io_context's guarantee that handlers 20 are only invoked from inside run(). 21 22* Where there is a single chain of asynchronous operations associated with a 23 connection (e.g. in a half duplex protocol implementation like HTTP) there is 24 no possibility of concurrent execution of the handlers. This is an implicit 25 strand. 26 27* An explicit strand is an instance of `strand<>` or `io_context::strand`. All 28 event handler function objects need to be bound to the strand using 29 `boost::asio::bind_executor()` or otherwise posted/dispatched through the strand 30 object. 31 32In the case of composed asynchronous operations, such as `async_read()` or 33`async_read_until()`, if a completion handler goes through a strand, then all 34intermediate handlers should also go through the same strand. This is needed to 35ensure thread safe access for any objects that are shared between the caller 36and the composed operation (in the case of `async_read()` it's the socket, 37which the caller can `close()` to cancel the operation). 38 39To achieve this, all asynchronous operations obtain the handler's associated 40executor by using the `get_associated_executor` function. For example: 41 42 boost::asio::associated_executor_t<Handler> a = boost::asio::get_associated_executor(h); 43 44The associated executor must satisfy the Executor requirements. It will be used 45by the asynchronous operation to submit both intermediate and final handlers 46for execution. 47 48The executor may be customised for a particular handler type by specifying a 49nested type `executor_type` and member function `get_executor()`: 50 51 class my_handler 52 { 53 public: 54 // Custom implementation of Executor type requirements. 55 typedef my_executor executor_type; 56 57 // Return a custom executor implementation. 58 executor_type get_executor() const noexcept 59 { 60 return my_executor(); 61 } 62 63 void operator()() { ... } 64 }; 65 66In more complex cases, the `associated_executor` template may be partially 67specialised directly: 68 69 struct my_handler 70 { 71 void operator()() { ... } 72 }; 73 74 namespace boost { namespace asio { 75 76 template <class Executor> 77 struct associated_executor<my_handler, Executor> 78 { 79 // Custom implementation of Executor type requirements. 80 typedef my_executor type; 81 82 // Return a custom executor implementation. 83 static type get(const my_handler&, 84 const Executor& = Executor()) noexcept 85 { 86 return my_executor(); 87 } 88 }; 89 90 } } // namespace boost::asio 91 92The `boost::asio::bind_executor()` function is a helper to bind a specific executor 93object, such as a strand, to a completion handler. This binding automatically 94associates an executor as shown above. For example, to bind a strand to a 95completion handler we would simply write: 96 97 my_socket.async_read_some(my_buffer, 98 boost::asio::bind_executor(my_strand, 99 [](error_code ec, size_t length) 100 { 101 // ... 102 })); 103 104[heading See Also] 105 106[link boost_asio.reference.associated_executor associated_executor], 107[link boost_asio.reference.get_associated_executor get_associated_executor], 108[link boost_asio.reference.bind_executor bind_executor], 109[link boost_asio.reference.strand strand], 110[link boost_asio.reference.io_context__strand io_context::strand], 111[link boost_asio.tutorial.tuttimer5 tutorial Timer.5], 112[link boost_asio.examples.cpp03_examples.http_server_3 HTTP server 3 example]. 113 114[endsect] 115