asio-integration.html 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  2. <html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  3. <title>ASIO/Networking TS : Boost &lt; 1.70 - Boost.Outcome documentation</title>
  4. <link rel="stylesheet" href="../css/boost.css" type="text/css">
  5. <meta name="generator" content="Hugo 0.52 with Boostdoc theme">
  6. <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
  7. <link rel="icon" href="../images/favicon.ico" type="image/ico"/>
  8. <body><div class="spirit-nav">
  9. <a accesskey="p" href="../recipes.html"><img src="../images/prev.png" alt="Prev"></a>
  10. <a accesskey="u" href="../recipes.html"><img src="../images/up.png" alt="Up"></a>
  11. <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">
  12. <div class="titlepage"><div><div><h1 style="clear: both">ASIO/Networking TS : Boost &lt; 1.70</h1></div></div></div>
  13. <div class="toc"><dl class="toc">
  14. <dt>
  15. <dd><dl>
  16. <dt>
  17. <dd><dl>
  18. <dt><a href="#compatibility-note">Compatibility note</a></dt>
  19. <dt><a href="#use-case">Use case</a></dt>
  20. <dt><a href="#implementation">Implementation</a></dt>
  21. </dl></dd></dt>
  22. </dl></dd></dt>
  23. </dl>
  24. </div>
  25. <p><em>Thanks to <a href="https://github.com/cstratopoulos">Christos Stratopoulos</a> for this Outcome recipe.</em></p>
  26. <hr />
  27. <h3 id="compatibility-note">Compatibility note</h3>
  28. <p>This recipe targets Boost versions before 1.70, where coroutine support is based around
  29. the <code>asio::experimental::this_coro::token</code> completion token. For integration with Boost
  30. versions 1.70 and onward, see <a href="asio-integration-1-70">this recipe</a>.</p>
  31. <hr />
  32. <h3 id="use-case">Use case</h3>
  33. <p><a href="https://www.boost.org/doc/libs/develop/doc/html/boost_asio.html">Boost.ASIO</a>
  34. and <a href="https://think-async.com/Asio/">standalone ASIO</a> provide the
  35. <a href="https://www.boost.org/doc/libs/develop/doc/html/boost_asio/reference/async_result.html"><code>async_result</code></a>
  36. customisation point for adapting arbitrary third party libraries, such as Outcome, into ASIO.</p>
  37. <p>Historically in ASIO you need to pass completion handler instances
  38. to the ASIO asynchronous i/o initiation functions. These get executed when the i/o
  39. completes.</p>
  40. <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
  41. </span><span class="c1"></span> <span class="c1">// so it can be attached to the completion handler, hence the unique_ptr.
  42. </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">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">byte</span><span class="o">&gt;&gt;</span><span class="p">(</span><span class="mi">1024</span><span class="p">);</span>
  43. <span class="c1">// Begin an asynchronous socket read, upon completion invoke
  44. </span><span class="c1"></span> <span class="c1">// the lambda function specified
  45. </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">-&gt;</span><span class="n">data</span><span class="p">(),</span> <span class="n">buffer</span><span class="o">-&gt;</span><span class="n">size</span><span class="p">()),</span>
  46. <span class="c1">// Retain lifetime of the i/o buffer until completion
  47. </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">&amp;</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>
  48. <span class="c1">// Handle the buffer read
  49. </span><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">ec</span><span class="p">)</span>
  50. <span class="p">{</span>
  51. <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Buffer read failed with &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">ec</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
  52. <span class="k">return</span><span class="p">;</span>
  53. <span class="p">}</span>
  54. <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Read &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">bytes</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; bytes into buffer&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
  55. <span class="c1">// buffer will be dynamically freed now
  56. </span><span class="c1"></span> <span class="p">});</span>
  57. </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>
  58. <p>One of the big value adds of the Coroutines TS is the ability to not have to write
  59. so much boilerplate if you have a Coroutines supporting compiler:</p>
  60. <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
  61. </span><span class="c1"></span> <span class="c1">// operation executes, we can use stack allocation instead of dynamic
  62. </span><span class="c1"></span> <span class="c1">// allocation
  63. </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>
  64. <span class="c1">// Get an ASIO completion token for the current coroutine (requires
  65. </span><span class="c1"></span> <span class="c1">// Coroutines TS)
  66. </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">//
  67. </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>
  68. <span class="c1">// Asynchronously read data, suspending this coroutine until completion,
  69. </span><span class="c1"></span> <span class="c1">// returning the bytes of the data read into the result.
  70. </span><span class="c1"></span> <span class="k">try</span>
  71. <span class="p">{</span>
  72. <span class="n">size_t</span> <span class="n">bytesread</span> <span class="o">=</span> <span class="c1">//
  73. </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>
  74. <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Read &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">bytesread</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; bytes into buffer&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
  75. <span class="p">}</span>
  76. <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">&amp;</span><span class="n">e</span><span class="p">)</span>
  77. <span class="p">{</span>
  78. <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Buffer read failed with &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">e</span><span class="p">.</span><span class="n">what</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
  79. <span class="p">}</span>
  80. </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>
  81. <p>The default ASIO implementation always throws exceptions on failure through
  82. 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>
  83. token transformation recovers the option to use the <code>error_code</code> interface,
  84. but it suffers from the <a href="../motivation/error_codes.html">same drawbacks</a>
  85. that make pure error codes unappealing in the synchronous case.</p>
  86. <p>This recipe fixes that by making it possible for coroutinised
  87. i/o in ASIO to return a <code>result&lt;T&gt;</code>:</p>
  88. <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,
  89. </span><span class="c1"></span> <span class="c1">// returning the bytes of the data read into the result, or any failure.
  90. </span><span class="c1"></span> <span class="n">outcome</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">size_t</span><span class="p">,</span> <span class="n">error_code</span><span class="o">&gt;</span> <span class="n">bytesread</span> <span class="o">=</span> <span class="c1">//
  91. </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>
  92. <span class="c1">// Usage is exactly like ordinary Outcome. Note the lack of exception throw!
  93. </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>
  94. <span class="p">{</span>
  95. <span class="n">std</span><span class="o">::</span><span class="n">cerr</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Buffer read failed with &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">bytesread</span><span class="p">.</span><span class="n">error</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
  96. <span class="k">return</span><span class="p">;</span>
  97. <span class="p">}</span>
  98. <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Read &#34;</span> <span class="o">&lt;&lt;</span> <span class="n">bytesread</span><span class="p">.</span><span class="n">value</span><span class="p">()</span> <span class="o">&lt;&lt;</span> <span class="s">&#34; bytes into buffer&#34;</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
  99. </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>
  100. <hr />
  101. <h3 id="implementation">Implementation</h3>
  102. <div class="notices warning" style="background: url('../images/warning.png') top left no-repeat padding-box padding-box;">
  103. <div class="notices heading">warning</div>
  104. <div class="notices message"><p>The below involves a lot of ASIO voodoo. <strong>NO SUPPORT WILL BE GIVEN HERE FOR THE ASIO
  105. CODE BELOW</strong>. Please raise any questions or problems that you have with how to implement
  106. this sort of stuff in ASIO
  107. on <a href="https://stackoverflow.com/questions/tagged/boost-asio">Stackoverflow #boost-asio</a>.</p>
  108. </div>
  109. </div>
  110. <p>The real world, production-level recipe can be found at the bottom of this page.
  111. You ought to use that in any real world use case.</p>
  112. <p>It is however worth providing a walkthrough of a simplified edition of the real world
  113. recipe, as a lot of barely documented ASIO voodoo is involved. You should not
  114. use the code presented next in your own code, it is too simplified. But it should
  115. help you understand how the real implementation works.</p>
  116. <p>Firstly we need to define some helper type sugar and a factory function for wrapping
  117. any arbitrary third party completion token with that type sugar:</p>
  118. <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>
  119. <span class="p">{</span>
  120. <span class="c1">// Type sugar for wrapping an external completion token
  121. </span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">CompletionToken</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">as_result_t</span>
  122. <span class="p">{</span>
  123. <span class="n">CompletionToken</span> <span class="n">token</span><span class="p">;</span>
  124. <span class="p">};</span>
  125. <span class="p">}</span> <span class="c1">// namespace detail
  126. </span><span class="c1"></span>
  127. <span class="c1">// Factory function for wrapping a third party completion token with
  128. </span><span class="c1">// our type sugar
  129. </span><span class="c1"></span><span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">CompletionToken</span><span class="o">&gt;</span> <span class="c1">//
  130. </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">&amp;&amp;</span><span class="n">token</span><span class="p">)</span>
  131. <span class="p">{</span>
  132. <span class="k">return</span> <span class="n">detail</span><span class="o">::</span><span class="n">as_result_t</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="n">CompletionToken</span><span class="o">&gt;&gt;</span><span class="p">{</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">CompletionToken</span><span class="o">&gt;</span><span class="p">(</span><span class="n">token</span><span class="p">)};</span>
  133. <span class="p">};</span>
  134. </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>
  135. <p>Next we tell ASIO about a new completion token it ought to recognise by specialising
  136. <a href="https://www.boost.org/doc/libs/develop/doc/html/boost_asio/reference/async_result.html"><code>async_result</code></a>:</p>
  137. <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
  138. </span><span class="c1">// from our as_result() factory function. This implementation is
  139. </span><span class="c1">// for functions with handlers void(error_code, T) only.
  140. </span><span class="c1"></span><span class="k">template</span> <span class="o">&lt;</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">&gt;</span> <span class="c1">//
  141. </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">&lt;</span><span class="n">detail</span><span class="o">::</span><span class="n">as_result_t</span><span class="o">&lt;</span><span class="n">CompletionToken</span><span class="o">&gt;</span><span class="p">,</span> <span class="c1">//
  142. </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">&gt;</span> <span class="c1">//
  143. </span><span class="c1"></span>
  144. <span class="c1">// NOTE we subclass for an async result taking an outcome::result
  145. </span><span class="c1"></span> <span class="c1">// as its completion handler. We will mangle the void(error_code, T)
  146. </span><span class="c1"></span> <span class="c1">// completion handler into this completion handler below.
  147. </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">&lt;</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">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">error_code</span><span class="o">&gt;</span><span class="p">)</span><span class="o">&gt;</span>
  148. <span class="p">{</span>
  149. <span class="c1">// The result type we shall return
  150. </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">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">error_code</span><span class="o">&gt;</span><span class="p">;</span>
  151. <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">&lt;</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">&gt;</span><span class="p">;</span>
  152. <span class="c1">// The awaitable type to be returned by the initiating function,
  153. </span><span class="c1"></span> <span class="c1">// the co_await of which will yield a result_type
  154. </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>
  155. <span class="c1">// Get what would be the completion handler for the async_result
  156. </span><span class="c1"></span> <span class="c1">// whose completion handler is void(result_type)
  157. </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">//
  158. </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>
  159. </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>
  160. <p>The tricky part to understand is that our <code>async_result</code> specialisation inherits
  161. from an <code>async_result</code> for the supplied completion token type with a completion
  162. handler which consumes a <code>result&lt;T&gt;</code>. Our <code>async_result</code> is actually therefore
  163. the base <code>async_result</code>, but we layer on top a <code>completion_handler_type</code> with
  164. the <code>void(error_code, size_t)</code> signature which constructs from that a <code>result</code>:</p>
  165. <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
  166. </span><span class="c1"></span> <span class="c1">// handler
  167. </span><span class="c1"></span> <span class="k">struct</span> <span class="n">completion_handler_type</span>
  168. <span class="p">{</span>
  169. <span class="c1">// Pass through unwrapped completion token
  170. </span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">U</span><span class="o">&gt;</span>
  171. <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">&lt;</span><span class="n">U</span><span class="o">&gt;</span> <span class="o">&amp;&amp;</span><span class="n">ch</span><span class="p">)</span>
  172. <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">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="p">(</span><span class="n">ch</span><span class="p">.</span><span class="n">token</span><span class="p">))</span>
  173. <span class="p">{</span>
  174. <span class="p">}</span>
  175. <span class="c1">// Our completion handler spec
  176. </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>
  177. <span class="p">{</span>
  178. <span class="c1">// Call the underlying completion handler, whose
  179. </span><span class="c1"></span> <span class="c1">// completion function is void(result_type)
  180. </span><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">ec</span><span class="p">)</span>
  181. <span class="p">{</span>
  182. <span class="c1">// Complete with a failed result
  183. </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>
  184. <span class="k">return</span><span class="p">;</span>
  185. <span class="p">}</span>
  186. <span class="c1">// Complete with a successful result
  187. </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>
  188. <span class="p">}</span>
  189. <span class="n">result_type_completion_handler_type</span> <span class="n">_handler</span><span class="p">;</span>
  190. <span class="p">};</span>
  191. <span class="c1">// Initialise base with the underlying completion handler
  192. </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">&amp;</span><span class="n">h</span><span class="p">)</span>
  193. <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>
  194. <span class="p">{</span>
  195. <span class="p">}</span>
  196. <span class="k">using</span> <span class="n">_base</span><span class="o">::</span><span class="n">get</span><span class="p">;</span>
  197. <span class="p">};</span>
  198. </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>
  199. <p>To use, simply wrap the third party completion token with <code>as_result</code> to cause
  200. ASIO to return from <code>co_await</code> a <code>result</code> instead of throwing exceptions on
  201. failure:</p>
  202. <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>
  203. <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>
  204. <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>
  205. <span class="n">outcome</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">size_t</span><span class="p">,</span> <span class="n">error_code</span><span class="o">&gt;</span> <span class="n">bytesread</span> <span class="o">=</span>
  206. <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>
  207. </code></pre></div>
  208. <p>The real world production-level implementation below is a lot more complex than the
  209. above which has been deliberately simplified to aid exposition. The above
  210. should help you get up and running with the below, eventually.</p>
  211. <p>One again I would like to remind you that Outcome is not the appropriate place
  212. to seek help with ASIO voodoo. Please ask on
  213. <a href="https://stackoverflow.com/questions/tagged/boost-asio">Stackoverflow #boost-asio</a>.</p>
  214. <hr />
  215. <p>Here follows the real world, production-level adapation of Outcome into
  216. ASIO, written and maintained by <a href="https://github.com/cstratopoulos">Christos Stratopoulos</a>.
  217. If the following does not load due to Javascript being disabled, you can visit the gist at
  218. <a href="https://gist.github.com/cstratopoulos/901b5cdd41d07c6ce6d83798b09ecf9b/da584844f58353915dc2600fba959813f793b456">https://gist.github.com/cstratopoulos/901b5cdd41d07c6ce6d83798b09ecf9b/da584844f58353915dc2600fba959813f793b456</a>.</p>
  219. <script type="application/javascript" src="//gist.github.com/cstratopoulos/901b5cdd41d07c6ce6d83798b09ecf9b/da584844f58353915dc2600fba959813f793b456.js"></script>
  220. </div><p><small>Last revised: August 06, 2019 at 10:42:06 &#43;0100</small></p>
  221. <hr>
  222. <div class="spirit-nav">
  223. <a accesskey="p" href="../recipes.html"><img src="../images/prev.png" alt="Prev"></a>
  224. <a accesskey="u" href="../recipes.html"><img src="../images/up.png" alt="Up"></a>
  225. <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>
  226. </html>