Skip to content

Commit

Permalink
automatic commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Docs Deployment Bot committed Oct 17, 2024
1 parent ebdd78e commit e2bed5b
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 2 deletions.
3 changes: 2 additions & 1 deletion coro-introduction.html
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@
<p >When using a <code>co_*</code> function such as <code>co_message_create</code>, the request is sent immediately and the returned <a class="el" href="classdpp_1_1async.html" title="A co_await-able object handling an API call in parallel with the caller.">dpp::async</a> can be <code>co_await</code>-ed, at which point the coroutine suspends (pauses) and returns back to its caller; in other words, the program is free to go and do other things while the data is being retrieved and D++ will resume your coroutine when it has the data you need, which will be returned from the <code>co_await</code> expression.</p>
<dl class="section warning"><dt>Warning</dt><dd>As a rule of thumb when making coroutines, <b>always prefer taking parameters by value and avoid lambda capture</b>! See below for an explanation.</dd></dl>
<p>You may hear that coroutines are "writing async code as if it was sync", while this is sort of correct, it may limit your understanding and especially the dangers of coroutines. I find <b>they are best thought of as a shortcut for a state machine</b>, if you've ever written one, you know what this means. Think of the lambda as <em>its constructor</em>, in which captures are variable parameters. Think of the parameters passed to your lambda as data members in your state machine. When you <code>co_await</code> something, the state machine's function exits, the program goes back to the caller, at this point the calling function may return. References are kept as references in the state machine, which means by the time the state machine is resumed, the reference may be dangling: <a class="el" href="lambdas-and-locals.html">this is not good</a>!</p>
<p >Another way to think of them is just like callbacks but keeping the current scope intact. In fact this is exactly what it is, the co_* functions call the normal API calls, with a callback that resumes the coroutine, <em>in the callback thread</em>. This means you cannot rely on thread_local variables and need to keep in mind concurrency issues with global states, as your coroutine will be resumed in another thread than the one it started on. </p>
<p >Another way to think of them is just like callbacks but keeping the current scope intact. In fact this is exactly what it is, the co_* functions call the normal API calls, with a callback that resumes the coroutine, <em>in the callback thread</em>. This means you cannot rely on thread_local variables and need to keep in mind concurrency issues with global states, as your coroutine will be resumed in another thread than the one it started on.</p>
<p >It is also worth noting that coroutines can lead to cases where errors may fall through and remain uncaptured, requiring the user to manually handle the error. These exceptions occur because callbacks cannot be used in their typical manner, which can be observed <a href="https://github.com/brainboxdotcc/DPP/issues/1222">in the following issue</a> and the <a class="el" href="coro-simple-commands.html">sample coroutine code</a>. </p>
</div></div><!-- contents --><script src="https://giscus.app/client.js" data-repo="brainboxdotcc/dpp-comments" data-repo-id="R_kgDOHOY4xg" data-category="General" data-category-id="DIC_kwDOHOY4xs4CRYtj" data-mapping="pathname" data-strict="1" data-reactions-enabled="1" data-emit-metadata="1" data-input-position="top" data-theme="preferred_color_scheme" data-lang="en" data-loading="lazy" crossorigin="anonymous" async></script>
</div><!-- PageDoc -->
</div><!-- doc-content -->
Expand Down
3 changes: 2 additions & 1 deletion xml/coro-introduction.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
<para><simplesect kind="warning"><para>As a rule of thumb when making coroutines, <bold>always prefer taking parameters by value and avoid lambda capture</bold>! See below for an explanation.</para>
</simplesect>
You may hear that coroutines are &quot;writing async code as if it was sync&quot;, while this is sort of correct, it may limit your understanding and especially the dangers of coroutines. I find <bold>they are best thought of as a shortcut for a state machine</bold>, if you&apos;ve ever written one, you know what this means. Think of the lambda as <emphasis>its constructor</emphasis>, in which captures are variable parameters. Think of the parameters passed to your lambda as data members in your state machine. When you <computeroutput>co_await</computeroutput> something, the state machine&apos;s function exits, the program goes back to the caller, at this point the calling function may return. References are kept as references in the state machine, which means by the time the state machine is resumed, the reference may be dangling: <ref refid="lambdas-and-locals" kindref="compound">this is not good</ref>!</para>
<para>Another way to think of them is just like callbacks but keeping the current scope intact. In fact this is exactly what it is, the co_* functions call the normal API calls, with a callback that resumes the coroutine, <emphasis>in the callback thread</emphasis>. This means you cannot rely on thread_local variables and need to keep in mind concurrency issues with global states, as your coroutine will be resumed in another thread than the one it started on. </para>
<para>Another way to think of them is just like callbacks but keeping the current scope intact. In fact this is exactly what it is, the co_* functions call the normal API calls, with a callback that resumes the coroutine, <emphasis>in the callback thread</emphasis>. This means you cannot rely on thread_local variables and need to keep in mind concurrency issues with global states, as your coroutine will be resumed in another thread than the one it started on.</para>
<para>It is also worth noting that coroutines can lead to cases where errors may fall through and remain uncaptured, requiring the user to manually handle the error. These exceptions occur because callbacks cannot be used in their typical manner, which can be observed <ulink url="https://github.com/brainboxdotcc/DPP/issues/1222">in the following issue</ulink> and the <ref refid="coro-simple-commands" kindref="compound">sample coroutine code</ref>. </para>
</detaileddescription>
<location file="docpages/example_programs/using_coroutines/coro_introduction.md"/>
</compounddef>
Expand Down

0 comments on commit e2bed5b

Please sign in to comment.