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 initi
| 44 | // To enable this, when implementing an asynchronous operation we must package |
| 45 | // the initiation step as a function object. |
| 46 | struct async_write_message_initiation |
| 47 | { |
| 48 | // The initiation function object's call operator is passed the concrete |
| 49 | // completion handler produced by the completion token. This completion |
| 50 | // handler matches the asynchronous operation's completion handler signature, |
| 51 | // which in this example is: |
| 52 | // |
| 53 | // void(boost::system::error_code error, std::size_t) |
| 54 | // |
| 55 | // The initiation function object also receives any additional arguments |
| 56 | // required to start the operation. (Note: We could have instead passed these |
| 57 | // arguments as members in the initiaton function object. However, we should |
| 58 | // prefer to propagate them as function call arguments as this allows the |
| 59 | // completion token to optimise how they are passed. For example, a lazy |
| 60 | // future which defers initiation would need to make a decay-copy of the |
| 61 | // arguments, but when using a simple callback the arguments can be trivially |
| 62 | // forwarded straight through.) |
| 63 | template <typename CompletionHandler> |
| 64 | void operator()(CompletionHandler&& completion_handler, tcp::socket& socket, |
| 65 | const char* message, bool allow_partial_write) const |
| 66 | { |
| 67 | if (allow_partial_write) |
| 68 | { |
| 69 | // When delegating to an underlying operation we must take care to |
| 70 | // perfectly forward the completion handler. This ensures that our |
| 71 | // operation works correctly with move-only function objects as |
| 72 | // callbacks. |
| 73 | return socket.async_write_some( |
| 74 | boost::asio::buffer(message, std::strlen(message)), |
| 75 | std::forward<CompletionHandler>(completion_handler)); |
| 76 | } |
| 77 | else |
| 78 | { |
| 79 | // As above, we must perfectly forward the completion handler when calling |
| 80 | // the alternate underlying operation. |
| 81 | return boost::asio::async_write(socket, |
| 82 | boost::asio::buffer(message, std::strlen(message)), |
| 83 | std::forward<CompletionHandler>(completion_handler)); |
| 84 | } |
| 85 | } |
| 86 | }; |
| 87 | |
| 88 | template <typename CompletionToken> |
| 89 | auto async_write_message(tcp::socket& socket, |
no outgoing calls
no test coverage detected