2023-10-24 21:59:30 -04:00
< html >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8" >
< title > Compositions as Asynchronous Operations< / title >
< link rel = "stylesheet" href = "../../../boostbook.css" type = "text/css" >
< meta name = "generator" content = "DocBook XSL Stylesheets V1.75.2" >
< link rel = "home" href = "../../../index.html" title = "Asio" >
< link rel = "up" href = "../composition.html" title = "Composition and Completion Tokens" >
< link rel = "prev" href = "parallel_group.html" title = "Co-ordinating Parallel Operations" >
< link rel = "next" href = "token_adapters.html" title = "Completion Token Adapters" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< / head >
< body bgcolor = "white" text = "black" link = "#0000FF" vlink = "#840084" alink = "#0000FF" >
< table cellpadding = "2" width = "100%" > < tr > < td valign = "top" > < img alt = "asio C++ library" width = "250" height = "60" src = "../../../asio.png" > < / td > < / tr > < / table >
< hr >
< div class = "spirit-nav" >
< a accesskey = "p" href = "parallel_group.html" > < img src = "../../../prev.png" alt = "Prev" > < / a > < a accesskey = "u" href = "../composition.html" > < img src = "../../../up.png" alt = "Up" > < / a > < a accesskey = "h" href = "../../../index.html" > < img src = "../../../home.png" alt = "Home" > < / a > < a accesskey = "n" href = "token_adapters.html" > < img src = "../../../next.png" alt = "Next" > < / a >
< / div >
< div class = "section" >
< div class = "titlepage" > < div > < div > < h4 class = "title" >
< a name = "asio.overview.composition.compose" > < / a > < a class = "link" href = "compose.html" title = "Compositions as Asynchronous Operations" > Compositions as
Asynchronous Operations< / a >
< / h4 > < / div > < / div > < / div >
< p >
Application developers may wish to package their own compositions as conforming
< a class = "link" href = "../model/async_ops.html" title = "Asynchronous Operations" > asynchronous operations< / a >
within the < a class = "link" href = "../model.html" title = "Asynchronous Model" > asynchronous model< / a > .
Doing so facilitates seamless composition of these operations together
with the operations already provided by Asio.
< / p >
< p >
While these operations may be written from scratch to conform with the
< a class = "link" href = "../../reference/asynchronous_operations.html" title = "Requirements on asynchronous operations" > requirements on
asynchronous operations< / a > , Asio includes the < a class = "link" href = "../../reference/async_compose.html" title = "async_compose" > < code class = "computeroutput" > < span class = "identifier" > async_compose< / span > < / code > < / a > function to simplify
this process. The < code class = "computeroutput" > < span class = "identifier" > async_compose< / span > < / code >
implementation automatically provides an intermediate completion handler
that correctly propagates the < a class = "link" href = "../model/associators.html" title = "Associated Characteristics and Associators" > associated
characteristics< / a > and tracks outstanding work against the I/O executor
and completion executor.
< / p >
< p >
The following example illustrates an asynchronous echo loop (i.e. read,
followed by write, and so on), expressed as a simple state machine.
< / p >
< pre class = "programlisting" > < span class = "keyword" > struct< / span > < span class = "identifier" > async_echo_implementation< / span >
< span class = "special" > {< / span >
2023-10-25 13:08:15 -04:00
< span class = "identifier" > tcp< / span > < span class = "special" > ::< / span > < span class = "identifier" > socket< / span > < span class = "special" > & < / span > < span class = "identifier" > local_socket< / span > < span class = "special" > ;< / span >
2023-10-24 21:59:30 -04:00
< span class = "identifier" > asio< / span > < span class = "special" > ::< / span > < span class = "identifier" > mutable_buffer< / span > < span class = "identifier" > buffer_< / span > < span class = "special" > ;< / span >
< span class = "keyword" > enum< / span > < span class = "special" > {< / span > < span class = "identifier" > starting< / span > < span class = "special" > ,< / span > < span class = "identifier" > reading< / span > < span class = "special" > ,< / span > < span class = "identifier" > writing< / span > < span class = "special" > }< / span > < span class = "identifier" > state_< / span > < span class = "special" > ;< / span >
< span class = "keyword" > template< / span > < span class = "special" > < < / span > < span class = "keyword" > typename< / span > < span class = "identifier" > Self< / span > < span class = "special" > > < / span >
< span class = "keyword" > void< / span > < span class = "keyword" > operator< / span > < span class = "special" > ()(< / span > < span class = "identifier" > Self< / span > < span class = "special" > & < / span > < span class = "identifier" > self< / span > < span class = "special" > ,< / span >
< span class = "identifier" > asio< / span > < span class = "special" > ::< / span > < span class = "identifier" > error_code< / span > < span class = "identifier" > error< / span > < span class = "special" > =< / span > < span class = "special" > {},< / span >
< span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > size_t< / span > < span class = "identifier" > n< / span > < span class = "special" > =< / span > < span class = "number" > 0< / span > < span class = "special" > )< / span >
< span class = "special" > {< / span >
< span class = "keyword" > switch< / span > < span class = "special" > (< / span > < span class = "identifier" > state_< / span > < span class = "special" > )< / span >
< span class = "special" > {< / span >
< span class = "keyword" > case< / span > < span class = "identifier" > starting< / span > < span class = "special" > :< / span >
< span class = "identifier" > state_< / span > < span class = "special" > =< / span > < span class = "identifier" > reading< / span > < span class = "special" > ;< / span >
2023-10-25 13:08:15 -04:00
< span class = "identifier" > local_socket< / span > < span class = "special" > .< / span > < span class = "identifier" > async_read_some< / span > < span class = "special" > (< / span >
2023-10-24 21:59:30 -04:00
< span class = "identifier" > buffer_< / span > < span class = "special" > ,< / span > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > move< / span > < span class = "special" > (< / span > < span class = "identifier" > self< / span > < span class = "special" > ));< / span >
< span class = "keyword" > break< / span > < span class = "special" > ;< / span >
< span class = "keyword" > case< / span > < span class = "identifier" > reading< / span > < span class = "special" > :< / span >
< span class = "keyword" > if< / span > < span class = "special" > (< / span > < span class = "identifier" > error< / span > < span class = "special" > )< / span >
< span class = "special" > {< / span >
< span class = "identifier" > self< / span > < span class = "special" > .< / span > < span class = "identifier" > complete< / span > < span class = "special" > (< / span > < span class = "identifier" > error< / span > < span class = "special" > ,< / span > < span class = "number" > 0< / span > < span class = "special" > );< / span >
< span class = "special" > }< / span >
< span class = "keyword" > else< / span >
< span class = "special" > {< / span >
< span class = "identifier" > state_< / span > < span class = "special" > =< / span > < span class = "identifier" > writing< / span > < span class = "special" > ;< / span >
2023-10-25 13:08:15 -04:00
< span class = "identifier" > asio< / span > < span class = "special" > ::< / span > < span class = "identifier" > async_write< / span > < span class = "special" > (< / span > < span class = "identifier" > local_socket< / span > < span class = "special" > ,< / span > < span class = "identifier" > buffer_< / span > < span class = "special" > ,< / span >
2023-10-24 21:59:30 -04:00
< span class = "identifier" > asio< / span > < span class = "special" > ::< / span > < span class = "identifier" > transfer_exactly< / span > < span class = "special" > (< / span > < span class = "identifier" > n< / span > < span class = "special" > ),< / span >
< span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > move< / span > < span class = "special" > (< / span > < span class = "identifier" > self< / span > < span class = "special" > ));< / span >
< span class = "special" > }< / span >
< span class = "keyword" > break< / span > < span class = "special" > ;< / span >
< span class = "keyword" > case< / span > < span class = "identifier" > writing< / span > < span class = "special" > :< / span >
< span class = "identifier" > self< / span > < span class = "special" > .< / span > < span class = "identifier" > complete< / span > < span class = "special" > (< / span > < span class = "identifier" > error< / span > < span class = "special" > ,< / span > < span class = "identifier" > n< / span > < span class = "special" > );< / span >
< span class = "keyword" > break< / span > < span class = "special" > ;< / span >
< span class = "special" > }< / span >
< span class = "special" > }< / span >
< span class = "special" > };< / span >
< / pre >
< p >
This implementation is then used in an initiating function, which trivially
wraps < code class = "computeroutput" > < span class = "identifier" > async_compose< / span > < / code > :
< / p >
< pre class = "programlisting" > < span class = "keyword" > template< / span > < span class = "special" > < < / span > < span class = "keyword" > typename< / span > < span class = "identifier" > CompletionToken< / span > < span class = "special" > > < / span >
< span class = "keyword" > auto< / span > < span class = "identifier" > async_echo< / span > < span class = "special" > (< / span > < span class = "identifier" > tcp< / span > < span class = "special" > ::< / span > < span class = "identifier" > socket< / span > < span class = "special" > & < / span > < span class = "identifier" > socket< / span > < span class = "special" > ,< / span >
< span class = "identifier" > asio< / span > < span class = "special" > ::< / span > < span class = "identifier" > mutable_buffer< / span > < span class = "identifier" > buffer< / span > < span class = "special" > ,< / span >
< span class = "identifier" > CompletionToken< / span > < span class = "special" > & & < / span > < span class = "identifier" > token< / span > < span class = "special" > )< / span > < span class = "special" > -> < / span >
< span class = "keyword" > typename< / span > < span class = "identifier" > asio< / span > < span class = "special" > ::< / span > < span class = "identifier" > async_result< / span > < span class = "special" > < < / span >
< span class = "keyword" > typename< / span > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > decay< / span > < span class = "special" > < < / span > < span class = "identifier" > CompletionToken< / span > < span class = "special" > > ::< / span > < span class = "identifier" > type< / span > < span class = "special" > ,< / span >
< span class = "keyword" > void< / span > < span class = "special" > (< / span > < span class = "identifier" > asio< / span > < span class = "special" > ::< / span > < span class = "identifier" > error_code< / span > < span class = "special" > ,< / span > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > size_t< / span > < span class = "special" > )> ::< / span > < span class = "identifier" > return_type< / span >
< span class = "special" > {< / span >
< span class = "keyword" > return< / span > < span class = "identifier" > asio< / span > < span class = "special" > ::< / span > < span class = "identifier" > async_compose< / span > < span class = "special" > < < / span > < span class = "identifier" > CompletionToken< / span > < span class = "special" > ,< / span >
< span class = "keyword" > void< / span > < span class = "special" > (< / span > < span class = "identifier" > asio< / span > < span class = "special" > ::< / span > < span class = "identifier" > error_code< / span > < span class = "special" > ,< / span > < span class = "identifier" > std< / span > < span class = "special" > ::< / span > < span class = "identifier" > size_t< / span > < span class = "special" > )> (< / span >
< span class = "identifier" > async_echo_implementation< / span > < span class = "special" > {< / span > < span class = "identifier" > socket< / span > < span class = "special" > ,< / span > < span class = "identifier" > buffer< / span > < span class = "special" > ,< / span >
< span class = "identifier" > async_echo_implementation< / span > < span class = "special" > ::< / span > < span class = "identifier" > starting< / span > < span class = "special" > },< / span >
< span class = "identifier" > token< / span > < span class = "special" > ,< / span > < span class = "identifier" > socket< / span > < span class = "special" > );< / span >
< span class = "special" > }< / span >
< / pre >
< p >
Here, < code class = "computeroutput" > < span class = "identifier" > async_compose< / span > < / code > is
first passed the function object that contains the implementation of the
composed asynchronous operation. The first argument to the function object
is a non-const reference to the enclosing intermediate completion handler.
The remaining arguments are any arguments that originate from the completion
handlers of any asynchronous operations performed by the implementation.
< / p >
< p >
The < code class = "computeroutput" > < span class = "identifier" > async_compose< / span > < / code > function
is also passed the completion token, and zero or more I/O objects or I/O
executors for which outstanding work must be maintained.
< / p >
< h6 >
< a name = "asio.overview.composition.compose.h0" > < / a >
< span > < a name = "asio.overview.composition.compose.see_also" > < / a > < / span > < a class = "link" href = "compose.html#asio.overview.composition.compose.see_also" > See
Also< / a >
< / h6 >
< p >
< a class = "link" href = "../../reference/async_compose.html" title = "async_compose" > async_compose< / a > , < a class = "link" href = "../../examples/cpp11_examples.html#asio.examples.cpp11_examples.operations" > Operations examples (C++11)< / a > ,
< a class = "link" href = "../../examples/cpp14_examples.html#asio.examples.cpp14_examples.operations" > Operations examples
(C++14)< / a > .
< / p >
< / div >
< div class = "copyright-footer" > Copyright © 2003-2023 Christopher M. Kohlhoff< p >
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at < a href = "http://www.boost.org/LICENSE_1_0.txt" target = "_top" > http://www.boost.org/LICENSE_1_0.txt< / a > )
< / p >
< / div >
< hr >
< div class = "spirit-nav" >
< a accesskey = "p" href = "parallel_group.html" > < img src = "../../../prev.png" alt = "Prev" > < / a > < a accesskey = "u" href = "../composition.html" > < img src = "../../../up.png" alt = "Up" > < / a > < a accesskey = "h" href = "../../../index.html" > < img src = "../../../home.png" alt = "Home" > < / a > < a accesskey = "n" href = "token_adapters.html" > < img src = "../../../next.png" alt = "Next" > < / a >
< / div >
< / body >
< / html >