123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>ASIO/Networking TS : Boost < 1.70 - Boost.Outcome documentation</title>
- <link rel="stylesheet" href="../css/boost.css" type="text/css">
- <meta name="generator" content="Hugo 0.52 with Boostdoc theme">
- <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
- <link rel="icon" href="../images/favicon.ico" type="image/ico"/>
- <body><div class="spirit-nav">
- <a accesskey="p" href="../recipes.html"><img src="../images/prev.png" alt="Prev"></a>
- <a accesskey="u" href="../recipes.html"><img src="../images/up.png" alt="Up"></a>
- <a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="../recipes/asio-integration-1-70.html"><img src="../images/next.png" alt="Next"></a></div><div id="content">
- <div class="titlepage"><div><div><h1 style="clear: both">ASIO/Networking TS : Boost < 1.70</h1></div></div></div>
- <div class="toc"><dl class="toc">
- <dt>
- <dd><dl>
- <dt>
- <dd><dl>
- <dt><a href="#compatibility-note">Compatibility note</a></dt>
- <dt><a href="#use-case">Use case</a></dt>
- <dt><a href="#implementation">Implementation</a></dt>
- </dl></dd></dt>
- </dl></dd></dt>
- </dl>
- </div>
-
- <p><em>Thanks to <a href="https://github.com/cstratopoulos">Christos Stratopoulos</a> for this Outcome recipe.</em></p>
- <hr />
- <h3 id="compatibility-note">Compatibility note</h3>
- <p>This recipe targets Boost versions before 1.70, where coroutine support is based around
- the <code>asio::experimental::this_coro::token</code> completion token. For integration with Boost
- versions 1.70 and onward, see <a href="asio-integration-1-70">this recipe</a>.</p>
- <hr />
- <h3 id="use-case">Use case</h3>
- <p><a href="https://www.boost.org/doc/libs/develop/doc/html/boost_asio.html">Boost.ASIO</a>
- and <a href="https://think-async.com/Asio/">standalone ASIO</a> provide the
- <a href="https://www.boost.org/doc/libs/develop/doc/html/boost_asio/reference/async_result.html"><code>async_result</code></a>
- customisation point for adapting arbitrary third party libraries, such as Outcome, into ASIO.</p>
- <p>Historically in ASIO you need to pass completion handler instances
- to the ASIO asynchronous i/o initiation functions. These get executed when the i/o
- completes.</p>
- <div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"> <span class="c1">// Dynamically allocate a buffer to read into. This must be move-only
- </span><span class="c1"></span> <span class="c1">// so it can be attached to the completion handler, hence the unique_ptr.
- </span><span class="c1"></span> <span class="k">auto</span> <span class="n">buffer</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o"><</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o"><</span><span class="n">byte</span><span class="o">>></span><span class="p">(</span><span class="mi">1024</span><span class="p">);</span>
- <span class="c1">// Begin an asynchronous socket read, upon completion invoke
- </span><span class="c1"></span> <span class="c1">// the lambda function specified
- </span><span class="c1"></span> <span class="n">skt</span><span class="p">.</span><span class="n">async_read_some</span><span class="p">(</span><span class="n">asio</span><span class="o">::</span><span class="n">buffer</span><span class="p">(</span><span class="n">buffer</span><span class="o">-></span><span class="n">data</span><span class="p">(),</span> <span class="n">buffer</span><span class="o">-></span><span class="n">size</span><span class="p">()),</span>
- <span class="c1">// Retain lifetime of the i/o buffer until completion
- </span><span class="c1"></span> <span class="p">[</span><span class="n">buffer</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">buffer</span><span class="p">)](</span><span class="k">const</span> <span class="n">error_code</span> <span class="o">&</span><span class="n">ec</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">bytes</span><span class="p">)</span> <span class="p">{</span>
- <span class="c1">// Handle the buffer read
- </span><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">ec</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o"><<</span> <span class="s">"Buffer read failed with "</span> <span class="o"><<</span> <span class="n">ec</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
- <span class="k">return</span><span class="p">;</span>
- <span class="p">}</span>
- <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Read "</span> <span class="o"><<</span> <span class="n">bytes</span> <span class="o"><<</span> <span class="s">" bytes into buffer"</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
- <span class="c1">// buffer will be dynamically freed now
- </span><span class="c1"></span> <span class="p">});</span>
- </code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/boost-only/asio_integration.cpp#L47" class="code-snippet-url" target="_blank">View this code on Github</a></div>
- <p>One of the big value adds of the Coroutines TS is the ability to not have to write
- so much boilerplate if you have a Coroutines supporting compiler:</p>
- <div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"> <span class="c1">// As coroutines suspend the calling thread whilst an asynchronous
- </span><span class="c1"></span> <span class="c1">// operation executes, we can use stack allocation instead of dynamic
- </span><span class="c1"></span> <span class="c1">// allocation
- </span><span class="c1"></span> <span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">1024</span><span class="p">];</span>
- <span class="c1">// Get an ASIO completion token for the current coroutine (requires
- </span><span class="c1"></span> <span class="c1">// Coroutines TS)
- </span><span class="c1"></span> <span class="n">asio</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">await_token</span> <span class="n">token</span> <span class="o">=</span> <span class="c1">//
- </span><span class="c1"></span> <span class="n">co_await</span> <span class="n">asio</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">this_coro</span><span class="o">::</span><span class="n">token</span><span class="p">();</span>
- <span class="c1">// Asynchronously read data, suspending this coroutine until completion,
- </span><span class="c1"></span> <span class="c1">// returning the bytes of the data read into the result.
- </span><span class="c1"></span> <span class="k">try</span>
- <span class="p">{</span>
- <span class="n">size_t</span> <span class="n">bytesread</span> <span class="o">=</span> <span class="c1">//
- </span><span class="c1"></span> <span class="n">co_await</span> <span class="n">skt</span><span class="p">.</span><span class="n">async_read_some</span><span class="p">(</span><span class="n">asio</span><span class="o">::</span><span class="n">buffer</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="n">token</span><span class="p">);</span>
- <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Read "</span> <span class="o"><<</span> <span class="n">bytesread</span> <span class="o"><<</span> <span class="s">" bytes into buffer"</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
- <span class="p">}</span>
- <span class="k">catch</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">system_error</span> <span class="o">&</span><span class="n">e</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o"><<</span> <span class="s">"Buffer read failed with "</span> <span class="o"><<</span> <span class="n">e</span><span class="p">.</span><span class="n">what</span><span class="p">()</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
- <span class="p">}</span>
- </code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/boost-only/asio_integration.cpp#L73" class="code-snippet-url" target="_blank">View this code on Github</a></div>
- <p>The default ASIO implementation always throws exceptions on failure through
- its coroutine token transformation. The <a href="https://www.boost.org/doc/libs/develop/doc/html/boost_asio/reference/experimental__redirect_error.html"><code>redirect_error</code></a>
- token transformation recovers the option to use the <code>error_code</code> interface,
- but it suffers from the <a href="../motivation/error_codes.html">same drawbacks</a>
- that make pure error codes unappealing in the synchronous case.</p>
- <p>This recipe fixes that by making it possible for coroutinised
- i/o in ASIO to return a <code>result<T></code>:</p>
- <div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"> <span class="c1">// Asynchronously read data, suspending this coroutine until completion,
- </span><span class="c1"></span> <span class="c1">// returning the bytes of the data read into the result, or any failure.
- </span><span class="c1"></span> <span class="n">outcome</span><span class="o">::</span><span class="n">result</span><span class="o"><</span><span class="n">size_t</span><span class="p">,</span> <span class="n">error_code</span><span class="o">></span> <span class="n">bytesread</span> <span class="o">=</span> <span class="c1">//
- </span><span class="c1"></span> <span class="n">co_await</span> <span class="n">skt</span><span class="p">.</span><span class="n">async_read_some</span><span class="p">(</span><span class="n">asio</span><span class="o">::</span><span class="n">buffer</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="n">as_result</span><span class="p">(</span><span class="n">token</span><span class="p">));</span>
- <span class="c1">// Usage is exactly like ordinary Outcome. Note the lack of exception throw!
- </span><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">bytesread</span><span class="p">.</span><span class="n">has_error</span><span class="p">())</span>
- <span class="p">{</span>
- <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o"><<</span> <span class="s">"Buffer read failed with "</span> <span class="o"><<</span> <span class="n">bytesread</span><span class="p">.</span><span class="n">error</span><span class="p">()</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
- <span class="k">return</span><span class="p">;</span>
- <span class="p">}</span>
- <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o"><<</span> <span class="s">"Read "</span> <span class="o"><<</span> <span class="n">bytesread</span><span class="p">.</span><span class="n">value</span><span class="p">()</span> <span class="o"><<</span> <span class="s">" bytes into buffer"</span> <span class="o"><<</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
- </code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/boost-only/asio_integration.cpp#L200" class="code-snippet-url" target="_blank">View this code on Github</a></div>
- <hr />
- <h3 id="implementation">Implementation</h3>
- <div class="notices warning" style="background: url('../images/warning.png') top left no-repeat padding-box padding-box;">
- <div class="notices heading">warning</div>
- <div class="notices message"><p>The below involves a lot of ASIO voodoo. <strong>NO SUPPORT WILL BE GIVEN HERE FOR THE ASIO
- CODE BELOW</strong>. Please raise any questions or problems that you have with how to implement
- this sort of stuff in ASIO
- on <a href="https://stackoverflow.com/questions/tagged/boost-asio">Stackoverflow #boost-asio</a>.</p>
- </div>
- </div>
- <p>The real world, production-level recipe can be found at the bottom of this page.
- You ought to use that in any real world use case.</p>
- <p>It is however worth providing a walkthrough of a simplified edition of the real world
- recipe, as a lot of barely documented ASIO voodoo is involved. You should not
- use the code presented next in your own code, it is too simplified. But it should
- help you understand how the real implementation works.</p>
- <p>Firstly we need to define some helper type sugar and a factory function for wrapping
- any arbitrary third party completion token with that type sugar:</p>
- <div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">namespace</span> <span class="n">detail</span>
- <span class="p">{</span>
- <span class="c1">// Type sugar for wrapping an external completion token
- </span><span class="c1"></span> <span class="k">template</span> <span class="o"><</span><span class="k">class</span><span class="err"> </span><span class="nc">CompletionToken</span><span class="o">></span> <span class="k">struct</span> <span class="n">as_result_t</span>
- <span class="p">{</span>
- <span class="n">CompletionToken</span> <span class="n">token</span><span class="p">;</span>
- <span class="p">};</span>
- <span class="p">}</span> <span class="c1">// namespace detail
- </span><span class="c1"></span>
- <span class="c1">// Factory function for wrapping a third party completion token with
- </span><span class="c1">// our type sugar
- </span><span class="c1"></span><span class="k">template</span> <span class="o"><</span><span class="k">class</span><span class="err"> </span><span class="nc">CompletionToken</span><span class="o">></span> <span class="c1">//
- </span><span class="c1"></span><span class="kr">inline</span> <span class="k">auto</span> <span class="n">as_result</span><span class="p">(</span><span class="n">CompletionToken</span> <span class="o">&&</span><span class="n">token</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="k">return</span> <span class="n">detail</span><span class="o">::</span><span class="n">as_result_t</span><span class="o"><</span><span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o"><</span><span class="n">CompletionToken</span><span class="o">>></span><span class="p">{</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o"><</span><span class="n">CompletionToken</span><span class="o">></span><span class="p">(</span><span class="n">token</span><span class="p">)};</span>
- <span class="p">};</span>
- </code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/boost-only/asio_integration.cpp#L99" class="code-snippet-url" target="_blank">View this code on Github</a></div>
- <p>Next we tell ASIO about a new completion token it ought to recognise by specialising
- <a href="https://www.boost.org/doc/libs/develop/doc/html/boost_asio/reference/async_result.html"><code>async_result</code></a>:</p>
- <div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="c1">// Tell ASIO about a new kind of completion token, the kind returned
- </span><span class="c1">// from our as_result() factory function. This implementation is
- </span><span class="c1">// for functions with handlers void(error_code, T) only.
- </span><span class="c1"></span><span class="k">template</span> <span class="o"><</span><span class="k">class</span><span class="err"> </span><span class="nc">CompletionToken</span><span class="p">,</span> <span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="o">></span> <span class="c1">//
- </span><span class="c1"></span><span class="k">struct</span> <span class="n">asio</span><span class="o">::</span><span class="n">async_result</span><span class="o"><</span><span class="n">detail</span><span class="o">::</span><span class="n">as_result_t</span><span class="o"><</span><span class="n">CompletionToken</span><span class="o">></span><span class="p">,</span> <span class="c1">//
- </span><span class="c1"></span> <span class="kt">void</span><span class="p">(</span><span class="n">error_code</span><span class="p">,</span> <span class="n">T</span><span class="p">)</span><span class="o">></span> <span class="c1">//
- </span><span class="c1"></span>
- <span class="c1">// NOTE we subclass for an async result taking an outcome::result
- </span><span class="c1"></span> <span class="c1">// as its completion handler. We will mangle the void(error_code, T)
- </span><span class="c1"></span> <span class="c1">// completion handler into this completion handler below.
- </span><span class="c1"></span> <span class="o">:</span> <span class="k">public</span> <span class="n">asio</span><span class="o">::</span><span class="n">async_result</span><span class="o"><</span><span class="n">CompletionToken</span><span class="p">,</span> <span class="kt">void</span><span class="p">(</span><span class="n">outcome</span><span class="o">::</span><span class="n">result</span><span class="o"><</span><span class="n">T</span><span class="p">,</span> <span class="n">error_code</span><span class="o">></span><span class="p">)</span><span class="o">></span>
- <span class="p">{</span>
- <span class="c1">// The result type we shall return
- </span><span class="c1"></span> <span class="k">using</span> <span class="n">result_type</span> <span class="o">=</span> <span class="n">outcome</span><span class="o">::</span><span class="n">result</span><span class="o"><</span><span class="n">T</span><span class="p">,</span> <span class="n">error_code</span><span class="o">></span><span class="p">;</span>
- <span class="k">using</span> <span class="n">_base</span> <span class="o">=</span> <span class="n">asio</span><span class="o">::</span><span class="n">async_result</span><span class="o"><</span><span class="n">CompletionToken</span><span class="p">,</span> <span class="kt">void</span><span class="p">(</span><span class="n">result_type</span><span class="p">)</span><span class="o">></span><span class="p">;</span>
- <span class="c1">// The awaitable type to be returned by the initiating function,
- </span><span class="c1"></span> <span class="c1">// the co_await of which will yield a result_type
- </span><span class="c1"></span> <span class="k">using</span> <span class="n">return_type</span> <span class="o">=</span> <span class="k">typename</span> <span class="n">_base</span><span class="o">::</span><span class="n">return_type</span><span class="p">;</span>
- <span class="c1">// Get what would be the completion handler for the async_result
- </span><span class="c1"></span> <span class="c1">// whose completion handler is void(result_type)
- </span><span class="c1"></span> <span class="k">using</span> <span class="n">result_type_completion_handler_type</span> <span class="o">=</span> <span class="c1">//
- </span><span class="c1"></span> <span class="k">typename</span> <span class="n">_base</span><span class="o">::</span><span class="n">completion_handler_type</span><span class="p">;</span>
- </code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/boost-only/asio_integration.cpp#L118" class="code-snippet-url" target="_blank">View this code on Github</a></div>
- <p>The tricky part to understand is that our <code>async_result</code> specialisation inherits
- from an <code>async_result</code> for the supplied completion token type with a completion
- handler which consumes a <code>result<T></code>. Our <code>async_result</code> is actually therefore
- the base <code>async_result</code>, but we layer on top a <code>completion_handler_type</code> with
- the <code>void(error_code, size_t)</code> signature which constructs from that a <code>result</code>:</p>
- <div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"> <span class="c1">// Wrap that completion handler with void(error_code, T) converting
- </span><span class="c1"></span> <span class="c1">// handler
- </span><span class="c1"></span> <span class="k">struct</span> <span class="n">completion_handler_type</span>
- <span class="p">{</span>
- <span class="c1">// Pass through unwrapped completion token
- </span><span class="c1"></span> <span class="k">template</span> <span class="o"><</span><span class="k">class</span><span class="err"> </span><span class="nc">U</span><span class="o">></span>
- <span class="n">completion_handler_type</span><span class="p">(</span><span class="o">::</span><span class="n">detail</span><span class="o">::</span><span class="n">as_result_t</span><span class="o"><</span><span class="n">U</span><span class="o">></span> <span class="o">&&</span><span class="n">ch</span><span class="p">)</span>
- <span class="o">:</span> <span class="n">_handler</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o"><</span><span class="n">U</span><span class="o">></span><span class="p">(</span><span class="n">ch</span><span class="p">.</span><span class="n">token</span><span class="p">))</span>
- <span class="p">{</span>
- <span class="p">}</span>
- <span class="c1">// Our completion handler spec
- </span><span class="c1"></span> <span class="kt">void</span> <span class="k">operator</span><span class="p">()(</span><span class="n">error_code</span> <span class="n">ec</span><span class="p">,</span> <span class="n">T</span> <span class="n">v</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="c1">// Call the underlying completion handler, whose
- </span><span class="c1"></span> <span class="c1">// completion function is void(result_type)
- </span><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">ec</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="c1">// Complete with a failed result
- </span><span class="c1"></span> <span class="n">_handler</span><span class="p">(</span><span class="n">result_type</span><span class="p">(</span><span class="n">outcome</span><span class="o">::</span><span class="n">failure</span><span class="p">(</span><span class="n">ec</span><span class="p">)));</span>
- <span class="k">return</span><span class="p">;</span>
- <span class="p">}</span>
- <span class="c1">// Complete with a successful result
- </span><span class="c1"></span> <span class="n">_handler</span><span class="p">(</span><span class="n">result_type</span><span class="p">(</span><span class="n">outcome</span><span class="o">::</span><span class="n">success</span><span class="p">(</span><span class="n">v</span><span class="p">)));</span>
- <span class="p">}</span>
- <span class="n">result_type_completion_handler_type</span> <span class="n">_handler</span><span class="p">;</span>
- <span class="p">};</span>
- <span class="c1">// Initialise base with the underlying completion handler
- </span><span class="c1"></span> <span class="n">async_result</span><span class="p">(</span><span class="n">completion_handler_type</span> <span class="o">&</span><span class="n">h</span><span class="p">)</span>
- <span class="o">:</span> <span class="n">_base</span><span class="p">(</span><span class="n">h</span><span class="p">.</span><span class="n">_handler</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="p">}</span>
- <span class="k">using</span> <span class="n">_base</span><span class="o">::</span><span class="n">get</span><span class="p">;</span>
- <span class="p">};</span>
- </code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/boost-only/asio_integration.cpp#L143" class="code-snippet-url" target="_blank">View this code on Github</a></div>
- <p>To use, simply wrap the third party completion token with <code>as_result</code> to cause
- ASIO to return from <code>co_await</code> a <code>result</code> instead of throwing exceptions on
- failure:</p>
- <div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="kt">char</span> <span class="n">buffer</span><span class="p">[</span><span class="mi">1024</span><span class="p">];</span>
- <span class="n">asio</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">await_token</span> <span class="n">token</span> <span class="o">=</span>
- <span class="n">co_await</span> <span class="n">asio</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">this_coro</span><span class="o">::</span><span class="n">token</span><span class="p">();</span>
- <span class="n">outcome</span><span class="o">::</span><span class="n">result</span><span class="o"><</span><span class="n">size_t</span><span class="p">,</span> <span class="n">error_code</span><span class="o">></span> <span class="n">bytesread</span> <span class="o">=</span>
- <span class="n">co_await</span> <span class="n">skt</span><span class="p">.</span><span class="n">async_read_some</span><span class="p">(</span><span class="n">asio</span><span class="o">::</span><span class="n">buffer</span><span class="p">(</span><span class="n">buffer</span><span class="p">),</span> <span class="n">as_result</span><span class="p">(</span><span class="n">token</span><span class="p">));</span>
- </code></pre></div>
- <p>The real world production-level implementation below is a lot more complex than the
- above which has been deliberately simplified to aid exposition. The above
- should help you get up and running with the below, eventually.</p>
- <p>One again I would like to remind you that Outcome is not the appropriate place
- to seek help with ASIO voodoo. Please ask on
- <a href="https://stackoverflow.com/questions/tagged/boost-asio">Stackoverflow #boost-asio</a>.</p>
- <hr />
- <p>Here follows the real world, production-level adapation of Outcome into
- ASIO, written and maintained by <a href="https://github.com/cstratopoulos">Christos Stratopoulos</a>.
- If the following does not load due to Javascript being disabled, you can visit the gist at
- <a href="https://gist.github.com/cstratopoulos/901b5cdd41d07c6ce6d83798b09ecf9b/da584844f58353915dc2600fba959813f793b456">https://gist.github.com/cstratopoulos/901b5cdd41d07c6ce6d83798b09ecf9b/da584844f58353915dc2600fba959813f793b456</a>.</p>
- <script type="application/javascript" src="//gist.github.com/cstratopoulos/901b5cdd41d07c6ce6d83798b09ecf9b/da584844f58353915dc2600fba959813f793b456.js"></script>
- </div><p><small>Last revised: August 06, 2019 at 10:42:06 +0100</small></p>
- <hr>
- <div class="spirit-nav">
- <a accesskey="p" href="../recipes.html"><img src="../images/prev.png" alt="Prev"></a>
- <a accesskey="u" href="../recipes.html"><img src="../images/up.png" alt="Up"></a>
- <a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="../recipes/asio-integration-1-70.html"><img src="../images/next.png" alt="Next"></a></div></body>
- </html>
|