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