audit pass conclusion
This commit is contained in:
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html" class="active"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html" class="active"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html" class="active"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html" class="active"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html" class="active"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html" class="active"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html" class="active"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html" class="active"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html" class="active"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html" class="active"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<!-- Book generated using mdBook -->
|
<!-- Book generated using mdBook -->
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Futures - our main example - Futures Explained in 200 Lines of Rust</title>
|
<title>Implementing Futures - Futures Explained in 200 Lines of Rust</title>
|
||||||
|
|
||||||
|
|
||||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html" class="active"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html" class="active"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -773,8 +773,7 @@ which it awaits, and all that happens is that these state machines are polled
|
|||||||
until some "leaf future" in the end either returns <code>Ready</code> or <code>Pending</code>.</p>
|
until some "leaf future" in the end either returns <code>Ready</code> or <code>Pending</code>.</p>
|
||||||
<p>The way our example is right now, it's not much better than regular synchronous
|
<p>The way our example is right now, it's not much better than regular synchronous
|
||||||
code. For us to actually await multiple futures at the same time we somehow need
|
code. For us to actually await multiple futures at the same time we somehow need
|
||||||
to <code>spawn</code> them so they're polled once, but does not cause our thread to sleep
|
to <code>spawn</code> them so the executor starts running them concurrently.</p>
|
||||||
and wait for them one after one.</p>
|
|
||||||
<p>Our example as it stands now returns this:</p>
|
<p>Our example as it stands now returns this:</p>
|
||||||
<pre><code class="language-ignore">Future got 1 at time: 1.00.
|
<pre><code class="language-ignore">Future got 1 at time: 1.00.
|
||||||
Future got 2 at time: 3.00.
|
Future got 2 at time: 3.00.
|
||||||
@@ -788,11 +787,11 @@ implementing just that. You should have a pretty good understanding of the
|
|||||||
concept of Futures by now.</p>
|
concept of Futures by now.</p>
|
||||||
<p>The next step should be getting to know how more advanced runtimes work and
|
<p>The next step should be getting to know how more advanced runtimes work and
|
||||||
how they implement different ways of running Futures to completion.</p>
|
how they implement different ways of running Futures to completion.</p>
|
||||||
<p>I <a href="./conclusion.html#building-a-better-exectuor">challenge you to create a better version</a>.</p>
|
<p><a href="./conclusion.html#building-a-better-exectuor">If I were you I would read this next, and try to implement it for our example.</a>.</p>
|
||||||
<p>That's actually it for now. There are probably much more to learn, but I think it
|
<p>That's actually it for now. There are probably much more to learn, but I think it
|
||||||
will be easier once the fundamental concepts are there and that further
|
will be easier once the fundamental concepts are there and that further
|
||||||
exploration will get a lot easier. </p>
|
exploration will get a lot easier.</p>
|
||||||
<p>Don't forget the exercises in the last chapter 😊. Have fun until the next time! </p>
|
<p>Don't forget the exercises in the last chapter 😊.</p>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html" class="active"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html" class="active"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html" class="active">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html" class="active">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -152,69 +152,43 @@
|
|||||||
<h1><a class="header" href="#conclusion-and-exercises" id="conclusion-and-exercises">Conclusion and exercises</a></h1>
|
<h1><a class="header" href="#conclusion-and-exercises" id="conclusion-and-exercises">Conclusion and exercises</a></h1>
|
||||||
<p>Congratulations. Good job! If you got this far you must have stayed with me
|
<p>Congratulations. Good job! If you got this far you must have stayed with me
|
||||||
all the way. I hope you enjoyed the ride!</p>
|
all the way. I hope you enjoyed the ride!</p>
|
||||||
<p>I'll leave you with some predictions and a set of exercises I'm suggesting for
|
<p>Remember that you call always leave feedback, suggest improvements or ask questions
|
||||||
those interested.</p>
|
in the <a href="https://github.com/cfsamson/books-futures-explained/issues">issue_tracker</a> for this book.
|
||||||
<p>Futures will be more ergonomic to use with time. For example, instead of having
|
I'll try my best to respond to each one of them.</p>
|
||||||
to create a <code>RawWaker</code> and so on, the <code>Waker</code> will also be possible to implement
|
<p>I'll leave you with some suggestions for exercises if you want to explore a little further below.</p>
|
||||||
as a normal <code>Trait</code>. It's probably going to be pretty similar to
|
<p>Until next time!</p>
|
||||||
<a href="https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.13/futures/task/trait.ArcWake.html">ArcWake</a>.</p>
|
<h2><a class="header" href="#reader-exercises" id="reader-exercises">Reader exercises</a></h2>
|
||||||
<p>There will probably be several more improvements like this, but since relatively
|
<p>So our implementation has taken some obvious shortcuts and could use some improvement.
|
||||||
few people will actually need implement leaf Futures compared to those that use
|
Actually digging into the code and try things yourself is a good way to learn. Here are
|
||||||
them, focus will first and foremost be on how ergonomic it's to work with
|
some good exercises if you want to explore more:</p>
|
||||||
futures inside async/await functions and blocks.</p>
|
<h3><a class="header" href="#avoid-threadpark" id="avoid-threadpark">Avoid <code>thread::park</code></a></h3>
|
||||||
<p>It will still take some time for the ecosystem to migrate over to <code>Futures 3.0</code>
|
<p>The big problem using <code>Thread::park</code> and <code>Thread::unpark</code> is that the user can access these
|
||||||
but since the advantages are so huge, it will not be a split between libraries
|
same methods from their own code. Try to use another method to suspend our thread and wake
|
||||||
using <code>Futures 1.0</code> and libraries using <code>Futures 3.0</code> for long.</p>
|
it up again on our command. Some hints:</p>
|
||||||
<h1><a class="header" href="#reader-exercises" id="reader-exercises">Reader exercises</a></h1>
|
|
||||||
<p>So our implementation has taken some obvious shortcuts and could use some improvement. Actually digging into the code and try things yourself is a good
|
|
||||||
way to learn. Here are some good exercises if you want to explore more:</p>
|
|
||||||
<h2><a class="header" href="#avoid-threadpark" id="avoid-threadpark">Avoid <code>thread::park</code></a></h2>
|
|
||||||
<p>The big problem using <code>Thread::park</code> and <code>Thread::unpark</code> is that the user can access these same methods from their own code. Try to use another method to
|
|
||||||
suspend our thread and wake it up again on our command. Some hints:</p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Check out <code>CondVars</code>, here are two sources <a href="https://en.wikipedia.org/wiki/Monitor_(synchronization)#Condition_variables">Wikipedia</a> and the
|
<li>Check out <code>CondVars</code>, here are two sources <a href="https://en.wikipedia.org/wiki/Monitor_(synchronization)#Condition_variables">Wikipedia</a> and the
|
||||||
docs for <a href="https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html"><code>CondVar</code></a></li>
|
docs for <a href="https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html"><code>CondVar</code></a></li>
|
||||||
<li>Take a look at crates that help you with this exact problem like <a href="https://github.com/crossbeam-rs/crossbeam">Crossbeam </a>(specifically the <a href="https://docs.rs/crossbeam/0.7.3/crossbeam/sync/struct.Parker.html"><code>Parker</code></a>)</li>
|
<li>Take a look at crates that help you with this exact problem like <a href="https://github.com/crossbeam-rs/crossbeam">Crossbeam </a>(specifically the <a href="https://docs.rs/crossbeam/0.7.3/crossbeam/sync/struct.Parker.html"><code>Parker</code></a>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2><a class="header" href="#avoid-wrapping-the-whole-reactor-in-a-mutex-and-pass-it-around" id="avoid-wrapping-the-whole-reactor-in-a-mutex-and-pass-it-around">Avoid wrapping the whole <code>Reactor</code> in a mutex and pass it around</a></h2>
|
<h3><a class="header" href="#avoid-wrapping-the-whole-reactor-in-a-mutex-and-pass-it-around" id="avoid-wrapping-the-whole-reactor-in-a-mutex-and-pass-it-around">Avoid wrapping the whole <code>Reactor</code> in a mutex and pass it around</a></h3>
|
||||||
<p>First of all, protecting the whole <code>Reactor</code> and passing it around is overkill. We're only interested in synchronizing some parts of the information it contains. Try to refactor that out and only synchronize access to what's really needed.</p>
|
<p>First of all, protecting the whole <code>Reactor</code> and passing it around is overkill. We're only
|
||||||
|
interested in synchronizing some parts of the information it contains. Try to refactor that
|
||||||
|
out and only synchronize access to what's really needed.</p>
|
||||||
|
<p>I'd encourage you to have a look at how <a href="https://github.com/async-rs/async-std/blob/master/src/net/driver/mod.rs">the async_std driver is implemented</a>
|
||||||
|
and <a href="https://github.com/tokio-rs/tokio/blob/master/tokio/src/runtime/basic_scheduler.rs">how tokios scheduler is implemented</a> to get some inspiration.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Do you want to pass around a reference to this information using an <code>Arc</code>?</li>
|
<li>Do you want to pass around a reference to this information using an <code>Arc</code>?</li>
|
||||||
<li>Do you want to make a global <code>Reactor</code> so it can be accessed from anywhere?</li>
|
<li>Do you want to make a global <code>Reactor</code> so it can be accessed from anywhere?</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Next , using a <code>Mutex</code> as a synchronization mechanism might be overkill since many methods only reads data. </p>
|
<h3><a class="header" href="#building-a-better-exectuor" id="building-a-better-exectuor">Building a better exectuor</a></h3>
|
||||||
<ul>
|
|
||||||
<li>Could an <a href="https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html"><code>RwLock</code></a> be more efficient some places?</li>
|
|
||||||
<li>Could you use any of the synchronization mechanisms in <a href="https://github.com/crossbeam-rs/crossbeam">Crossbeam</a>?</li>
|
|
||||||
<li>Do you want to dig into <a href="https://cfsamsonbooks.gitbook.io/epoll-kqueue-iocp-explained/appendix-1/atomics-in-rust">atomics in Rust and implement a synchronization mechanism</a> of your own?</li>
|
|
||||||
</ul>
|
|
||||||
<h2><a class="header" href="#avoid-creating-a-new-waker-for-every-event" id="avoid-creating-a-new-waker-for-every-event">Avoid creating a new Waker for every event</a></h2>
|
|
||||||
<p>Right now we create a new instance of a Waker for every event we create. Is this really needed? </p>
|
|
||||||
<ul>
|
|
||||||
<li>Could we create one instance and then cache it (see <a href="https://stjepang.github.io/2020/01/25/build-your-own-block-on.html">this article from <code>u/sjepang</code></a>)?
|
|
||||||
<ul>
|
|
||||||
<li>Should we cache it in <code>thread_local!</code> storage?</li>
|
|
||||||
<li>Or should be cache it using a global constant?</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<h2><a class="header" href="#could-we-implement-more-methods-on-our-executor" id="could-we-implement-more-methods-on-our-executor">Could we implement more methods on our executor?</a></h2>
|
|
||||||
<p>What about CPU intensive tasks? Right now they'll prevent our executor thread from progressing an handling events. Could you create a thread pool and create a method to send such tasks to the thread pool instead together with a Waker which will wake up the executor thread once the CPU intensive task is done?</p>
|
|
||||||
<p>In both <code>async_std</code> and <code>tokio</code> this method is called <code>spawn_blocking</code>, a good place to start is to read the documentation and the code thy use to implement that.</p>
|
|
||||||
<h2><a class="header" href="#building-a-better-exectuor" id="building-a-better-exectuor">Building a better exectuor</a></h2>
|
|
||||||
<p>Right now, we can only run one and one future. Most runtimes has a <code>spawn</code>
|
<p>Right now, we can only run one and one future. Most runtimes has a <code>spawn</code>
|
||||||
function which let's you start off a future and <code>await</code> it later so you
|
function which let's you start off a future and <code>await</code> it later so you
|
||||||
can run multiple futures concurrently.</p>
|
can run multiple futures concurrently.</p>
|
||||||
<p>As I'm writing this <a href="https://github.com/stjepang">@stjepan</a> is writing a blog
|
<p>As I suggested in the start of this book, visiting <a href="https://stjepang.github.io/2020/01/31/build-your-own-executor.html">@stjepan'sblog series about implementing your own executors</a>
|
||||||
series about implementing your own executors, and he just released a post
|
is the place I would start and take it from there.</p>
|
||||||
on how to accomplish just this you can visit <a href="https://stjepang.github.io/2020/01/31/build-your-own-executor.html">here</a>.
|
|
||||||
He knows what he's talking about so I recommend following that.</p>
|
|
||||||
<p>In the <a href="https://github.com/cfsamson/examples-futures/tree/bonus_spawn">bonus_spawn</a>
|
|
||||||
branch of the example repository you can also find an extremely simplified
|
|
||||||
(and worse) way of accomplishing the same in only a few lines of code.</p>
|
|
||||||
<h2><a class="header" href="#further-reading" id="further-reading">Further reading</a></h2>
|
<h2><a class="header" href="#further-reading" id="further-reading">Further reading</a></h2>
|
||||||
<p>There are many great resources for further study. In addition to the RFCs and
|
<p>There are many great resources. In addition to the RFCs and articles I've already
|
||||||
articles I've already linked to in the book, here are some of my suggestions:</p>
|
linked to in the book, here are some of my suggestions:</p>
|
||||||
<p><a href="https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html">The official Asyc book</a></p>
|
<p><a href="https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html">The official Asyc book</a></p>
|
||||||
<p><a href="https://book.async.rs/">The async_std book</a></p>
|
<p><a href="https://book.async.rs/">The async_std book</a></p>
|
||||||
<p><a href="https://aturon.github.io/blog/2016/09/07/futures-design/">Aron Turon: Designing futures for Rust</a></p>
|
<p><a href="https://aturon.github.io/blog/2016/09/07/futures-design/">Aron Turon: Designing futures for Rust</a></p>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
/* Atelier-Dune Comment */
|
/* Atelier-Dune Comment */
|
||||||
.hljs-comment {
|
.hljs-comment {
|
||||||
color: rgb(68, 68, 68);;
|
color: rgb(160, 160, 160);;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
.hljs-quote {
|
.hljs-quote {
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html" class="active">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html" class="active">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
|
|
||||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
<div class="sidebar-scrollbox">
|
<div class="sidebar-scrollbox">
|
||||||
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Futures - our main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
<ol class="chapter"><li class="affix"><a href="introduction.html">Introduction</a></li><li><a href="0_background_information.html"><strong aria-hidden="true">1.</strong> Background information</a></li><li><a href="1_futures_in_rust.html"><strong aria-hidden="true">2.</strong> Futures in Rust</a></li><li><a href="2_waker_context.html"><strong aria-hidden="true">3.</strong> Waker and Context</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">6.</strong> Implementing Futures</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">7.</strong> Finished example (editable)</a></li><li class="affix"><a href="conclusion.html">Conclusion and exercises</a></li></ol>
|
||||||
</div>
|
</div>
|
||||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -2920,8 +2920,7 @@ which it awaits, and all that happens is that these state machines are polled
|
|||||||
until some "leaf future" in the end either returns <code>Ready</code> or <code>Pending</code>.</p>
|
until some "leaf future" in the end either returns <code>Ready</code> or <code>Pending</code>.</p>
|
||||||
<p>The way our example is right now, it's not much better than regular synchronous
|
<p>The way our example is right now, it's not much better than regular synchronous
|
||||||
code. For us to actually await multiple futures at the same time we somehow need
|
code. For us to actually await multiple futures at the same time we somehow need
|
||||||
to <code>spawn</code> them so they're polled once, but does not cause our thread to sleep
|
to <code>spawn</code> them so the executor starts running them concurrently.</p>
|
||||||
and wait for them one after one.</p>
|
|
||||||
<p>Our example as it stands now returns this:</p>
|
<p>Our example as it stands now returns this:</p>
|
||||||
<pre><code class="language-ignore">Future got 1 at time: 1.00.
|
<pre><code class="language-ignore">Future got 1 at time: 1.00.
|
||||||
Future got 2 at time: 3.00.
|
Future got 2 at time: 3.00.
|
||||||
@@ -2935,11 +2934,11 @@ implementing just that. You should have a pretty good understanding of the
|
|||||||
concept of Futures by now.</p>
|
concept of Futures by now.</p>
|
||||||
<p>The next step should be getting to know how more advanced runtimes work and
|
<p>The next step should be getting to know how more advanced runtimes work and
|
||||||
how they implement different ways of running Futures to completion.</p>
|
how they implement different ways of running Futures to completion.</p>
|
||||||
<p>I <a href="./conclusion.html#building-a-better-exectuor">challenge you to create a better version</a>.</p>
|
<p><a href="./conclusion.html#building-a-better-exectuor">If I were you I would read this next, and try to implement it for our example.</a>.</p>
|
||||||
<p>That's actually it for now. There are probably much more to learn, but I think it
|
<p>That's actually it for now. There are probably much more to learn, but I think it
|
||||||
will be easier once the fundamental concepts are there and that further
|
will be easier once the fundamental concepts are there and that further
|
||||||
exploration will get a lot easier. </p>
|
exploration will get a lot easier.</p>
|
||||||
<p>Don't forget the exercises in the last chapter 😊. Have fun until the next time! </p>
|
<p>Don't forget the exercises in the last chapter 😊.</p>
|
||||||
<h1><a class="header" href="#our-finished-code" id="our-finished-code">Our finished code</a></h1>
|
<h1><a class="header" href="#our-finished-code" id="our-finished-code">Our finished code</a></h1>
|
||||||
<p>Here is the whole example. You can edit it right here in your browser and
|
<p>Here is the whole example. You can edit it right here in your browser and
|
||||||
run it yourself. Have fun!</p>
|
run it yourself. Have fun!</p>
|
||||||
@@ -3138,69 +3137,43 @@ impl Drop for Reactor {
|
|||||||
<h1><a class="header" href="#conclusion-and-exercises" id="conclusion-and-exercises">Conclusion and exercises</a></h1>
|
<h1><a class="header" href="#conclusion-and-exercises" id="conclusion-and-exercises">Conclusion and exercises</a></h1>
|
||||||
<p>Congratulations. Good job! If you got this far you must have stayed with me
|
<p>Congratulations. Good job! If you got this far you must have stayed with me
|
||||||
all the way. I hope you enjoyed the ride!</p>
|
all the way. I hope you enjoyed the ride!</p>
|
||||||
<p>I'll leave you with some predictions and a set of exercises I'm suggesting for
|
<p>Remember that you call always leave feedback, suggest improvements or ask questions
|
||||||
those interested.</p>
|
in the <a href="https://github.com/cfsamson/books-futures-explained/issues">issue_tracker</a> for this book.
|
||||||
<p>Futures will be more ergonomic to use with time. For example, instead of having
|
I'll try my best to respond to each one of them.</p>
|
||||||
to create a <code>RawWaker</code> and so on, the <code>Waker</code> will also be possible to implement
|
<p>I'll leave you with some suggestions for exercises if you want to explore a little further below.</p>
|
||||||
as a normal <code>Trait</code>. It's probably going to be pretty similar to
|
<p>Until next time!</p>
|
||||||
<a href="https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.13/futures/task/trait.ArcWake.html">ArcWake</a>.</p>
|
<h2><a class="header" href="#reader-exercises" id="reader-exercises">Reader exercises</a></h2>
|
||||||
<p>There will probably be several more improvements like this, but since relatively
|
<p>So our implementation has taken some obvious shortcuts and could use some improvement.
|
||||||
few people will actually need implement leaf Futures compared to those that use
|
Actually digging into the code and try things yourself is a good way to learn. Here are
|
||||||
them, focus will first and foremost be on how ergonomic it's to work with
|
some good exercises if you want to explore more:</p>
|
||||||
futures inside async/await functions and blocks.</p>
|
<h3><a class="header" href="#avoid-threadpark" id="avoid-threadpark">Avoid <code>thread::park</code></a></h3>
|
||||||
<p>It will still take some time for the ecosystem to migrate over to <code>Futures 3.0</code>
|
<p>The big problem using <code>Thread::park</code> and <code>Thread::unpark</code> is that the user can access these
|
||||||
but since the advantages are so huge, it will not be a split between libraries
|
same methods from their own code. Try to use another method to suspend our thread and wake
|
||||||
using <code>Futures 1.0</code> and libraries using <code>Futures 3.0</code> for long.</p>
|
it up again on our command. Some hints:</p>
|
||||||
<h1><a class="header" href="#reader-exercises" id="reader-exercises">Reader exercises</a></h1>
|
|
||||||
<p>So our implementation has taken some obvious shortcuts and could use some improvement. Actually digging into the code and try things yourself is a good
|
|
||||||
way to learn. Here are some good exercises if you want to explore more:</p>
|
|
||||||
<h2><a class="header" href="#avoid-threadpark" id="avoid-threadpark">Avoid <code>thread::park</code></a></h2>
|
|
||||||
<p>The big problem using <code>Thread::park</code> and <code>Thread::unpark</code> is that the user can access these same methods from their own code. Try to use another method to
|
|
||||||
suspend our thread and wake it up again on our command. Some hints:</p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Check out <code>CondVars</code>, here are two sources <a href="https://en.wikipedia.org/wiki/Monitor_(synchronization)#Condition_variables">Wikipedia</a> and the
|
<li>Check out <code>CondVars</code>, here are two sources <a href="https://en.wikipedia.org/wiki/Monitor_(synchronization)#Condition_variables">Wikipedia</a> and the
|
||||||
docs for <a href="https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html"><code>CondVar</code></a></li>
|
docs for <a href="https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html"><code>CondVar</code></a></li>
|
||||||
<li>Take a look at crates that help you with this exact problem like <a href="https://github.com/crossbeam-rs/crossbeam">Crossbeam </a>(specifically the <a href="https://docs.rs/crossbeam/0.7.3/crossbeam/sync/struct.Parker.html"><code>Parker</code></a>)</li>
|
<li>Take a look at crates that help you with this exact problem like <a href="https://github.com/crossbeam-rs/crossbeam">Crossbeam </a>(specifically the <a href="https://docs.rs/crossbeam/0.7.3/crossbeam/sync/struct.Parker.html"><code>Parker</code></a>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2><a class="header" href="#avoid-wrapping-the-whole-reactor-in-a-mutex-and-pass-it-around" id="avoid-wrapping-the-whole-reactor-in-a-mutex-and-pass-it-around">Avoid wrapping the whole <code>Reactor</code> in a mutex and pass it around</a></h2>
|
<h3><a class="header" href="#avoid-wrapping-the-whole-reactor-in-a-mutex-and-pass-it-around" id="avoid-wrapping-the-whole-reactor-in-a-mutex-and-pass-it-around">Avoid wrapping the whole <code>Reactor</code> in a mutex and pass it around</a></h3>
|
||||||
<p>First of all, protecting the whole <code>Reactor</code> and passing it around is overkill. We're only interested in synchronizing some parts of the information it contains. Try to refactor that out and only synchronize access to what's really needed.</p>
|
<p>First of all, protecting the whole <code>Reactor</code> and passing it around is overkill. We're only
|
||||||
|
interested in synchronizing some parts of the information it contains. Try to refactor that
|
||||||
|
out and only synchronize access to what's really needed.</p>
|
||||||
|
<p>I'd encourage you to have a look at how <a href="https://github.com/async-rs/async-std/blob/master/src/net/driver/mod.rs">the async_std driver is implemented</a>
|
||||||
|
and <a href="https://github.com/tokio-rs/tokio/blob/master/tokio/src/runtime/basic_scheduler.rs">how tokios scheduler is implemented</a> to get some inspiration.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Do you want to pass around a reference to this information using an <code>Arc</code>?</li>
|
<li>Do you want to pass around a reference to this information using an <code>Arc</code>?</li>
|
||||||
<li>Do you want to make a global <code>Reactor</code> so it can be accessed from anywhere?</li>
|
<li>Do you want to make a global <code>Reactor</code> so it can be accessed from anywhere?</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Next , using a <code>Mutex</code> as a synchronization mechanism might be overkill since many methods only reads data. </p>
|
<h3><a class="header" href="#building-a-better-exectuor" id="building-a-better-exectuor">Building a better exectuor</a></h3>
|
||||||
<ul>
|
|
||||||
<li>Could an <a href="https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html"><code>RwLock</code></a> be more efficient some places?</li>
|
|
||||||
<li>Could you use any of the synchronization mechanisms in <a href="https://github.com/crossbeam-rs/crossbeam">Crossbeam</a>?</li>
|
|
||||||
<li>Do you want to dig into <a href="https://cfsamsonbooks.gitbook.io/epoll-kqueue-iocp-explained/appendix-1/atomics-in-rust">atomics in Rust and implement a synchronization mechanism</a> of your own?</li>
|
|
||||||
</ul>
|
|
||||||
<h2><a class="header" href="#avoid-creating-a-new-waker-for-every-event" id="avoid-creating-a-new-waker-for-every-event">Avoid creating a new Waker for every event</a></h2>
|
|
||||||
<p>Right now we create a new instance of a Waker for every event we create. Is this really needed? </p>
|
|
||||||
<ul>
|
|
||||||
<li>Could we create one instance and then cache it (see <a href="https://stjepang.github.io/2020/01/25/build-your-own-block-on.html">this article from <code>u/sjepang</code></a>)?
|
|
||||||
<ul>
|
|
||||||
<li>Should we cache it in <code>thread_local!</code> storage?</li>
|
|
||||||
<li>Or should be cache it using a global constant?</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<h2><a class="header" href="#could-we-implement-more-methods-on-our-executor" id="could-we-implement-more-methods-on-our-executor">Could we implement more methods on our executor?</a></h2>
|
|
||||||
<p>What about CPU intensive tasks? Right now they'll prevent our executor thread from progressing an handling events. Could you create a thread pool and create a method to send such tasks to the thread pool instead together with a Waker which will wake up the executor thread once the CPU intensive task is done?</p>
|
|
||||||
<p>In both <code>async_std</code> and <code>tokio</code> this method is called <code>spawn_blocking</code>, a good place to start is to read the documentation and the code thy use to implement that.</p>
|
|
||||||
<h2><a class="header" href="#building-a-better-exectuor" id="building-a-better-exectuor">Building a better exectuor</a></h2>
|
|
||||||
<p>Right now, we can only run one and one future. Most runtimes has a <code>spawn</code>
|
<p>Right now, we can only run one and one future. Most runtimes has a <code>spawn</code>
|
||||||
function which let's you start off a future and <code>await</code> it later so you
|
function which let's you start off a future and <code>await</code> it later so you
|
||||||
can run multiple futures concurrently.</p>
|
can run multiple futures concurrently.</p>
|
||||||
<p>As I'm writing this <a href="https://github.com/stjepang">@stjepan</a> is writing a blog
|
<p>As I suggested in the start of this book, visiting <a href="https://stjepang.github.io/2020/01/31/build-your-own-executor.html">@stjepan'sblog series about implementing your own executors</a>
|
||||||
series about implementing your own executors, and he just released a post
|
is the place I would start and take it from there.</p>
|
||||||
on how to accomplish just this you can visit <a href="https://stjepang.github.io/2020/01/31/build-your-own-executor.html">here</a>.
|
|
||||||
He knows what he's talking about so I recommend following that.</p>
|
|
||||||
<p>In the <a href="https://github.com/cfsamson/examples-futures/tree/bonus_spawn">bonus_spawn</a>
|
|
||||||
branch of the example repository you can also find an extremely simplified
|
|
||||||
(and worse) way of accomplishing the same in only a few lines of code.</p>
|
|
||||||
<h2><a class="header" href="#further-reading" id="further-reading">Further reading</a></h2>
|
<h2><a class="header" href="#further-reading" id="further-reading">Further reading</a></h2>
|
||||||
<p>There are many great resources for further study. In addition to the RFCs and
|
<p>There are many great resources. In addition to the RFCs and articles I've already
|
||||||
articles I've already linked to in the book, here are some of my suggestions:</p>
|
linked to in the book, here are some of my suggestions:</p>
|
||||||
<p><a href="https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html">The official Asyc book</a></p>
|
<p><a href="https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html">The official Asyc book</a></p>
|
||||||
<p><a href="https://book.async.rs/">The async_std book</a></p>
|
<p><a href="https://book.async.rs/">The async_std book</a></p>
|
||||||
<p><a href="https://aturon.github.io/blog/2016/09/07/futures-design/">Aron Turon: Designing futures for Rust</a></p>
|
<p><a href="https://aturon.github.io/blog/2016/09/07/futures-design/">Aron Turon: Designing futures for Rust</a></p>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -672,8 +672,7 @@ until some "leaf future" in the end either returns `Ready` or `Pending`.
|
|||||||
|
|
||||||
The way our example is right now, it's not much better than regular synchronous
|
The way our example is right now, it's not much better than regular synchronous
|
||||||
code. For us to actually await multiple futures at the same time we somehow need
|
code. For us to actually await multiple futures at the same time we somehow need
|
||||||
to `spawn` them so they're polled once, but does not cause our thread to sleep
|
to `spawn` them so the executor starts running them concurrently.
|
||||||
and wait for them one after one.
|
|
||||||
|
|
||||||
Our example as it stands now returns this:
|
Our example as it stands now returns this:
|
||||||
|
|
||||||
@@ -696,13 +695,13 @@ concept of Futures by now.
|
|||||||
The next step should be getting to know how more advanced runtimes work and
|
The next step should be getting to know how more advanced runtimes work and
|
||||||
how they implement different ways of running Futures to completion.
|
how they implement different ways of running Futures to completion.
|
||||||
|
|
||||||
I [challenge you to create a better version](./conclusion.md#building-a-better-exectuor).
|
[If I were you I would read this next, and try to implement it for our example.](./conclusion.md#building-a-better-exectuor).
|
||||||
|
|
||||||
That's actually it for now. There are probably much more to learn, but I think it
|
That's actually it for now. There are probably much more to learn, but I think it
|
||||||
will be easier once the fundamental concepts are there and that further
|
will be easier once the fundamental concepts are there and that further
|
||||||
exploration will get a lot easier.
|
exploration will get a lot easier.
|
||||||
|
|
||||||
Don't forget the exercises in the last chapter 😊. Have fun until the next time!
|
Don't forget the exercises in the last chapter 😊.
|
||||||
|
|
||||||
[mio]: https://github.com/tokio-rs/mio
|
[mio]: https://github.com/tokio-rs/mio
|
||||||
[arc_wake]: https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.13/futures/task/trait.ArcWake.html
|
[arc_wake]: https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.13/futures/task/trait.ArcWake.html
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
- [Waker and Context](./2_waker_context.md)
|
- [Waker and Context](./2_waker_context.md)
|
||||||
- [Generators](./3_generators_pin.md)
|
- [Generators](./3_generators_pin.md)
|
||||||
- [Pin](./4_pin.md)
|
- [Pin](./4_pin.md)
|
||||||
- [Futures - our main example](./6_future_example.md)
|
- [Implementing Futures](./6_future_example.md)
|
||||||
- [Finished example (editable)](./8_finished_example.md)
|
- [Finished example (editable)](./8_finished_example.md)
|
||||||
|
|
||||||
[Conclusion and exercises](./conclusion.md)
|
[Conclusion and exercises](./conclusion.md)
|
||||||
|
|||||||
@@ -3,83 +3,55 @@
|
|||||||
Congratulations. Good job! If you got this far you must have stayed with me
|
Congratulations. Good job! If you got this far you must have stayed with me
|
||||||
all the way. I hope you enjoyed the ride!
|
all the way. I hope you enjoyed the ride!
|
||||||
|
|
||||||
I'll leave you with some predictions and a set of exercises I'm suggesting for
|
Remember that you call always leave feedback, suggest improvements or ask questions
|
||||||
those interested.
|
in the [issue_tracker](https://github.com/cfsamson/books-futures-explained/issues) for this book.
|
||||||
|
I'll try my best to respond to each one of them.
|
||||||
|
|
||||||
Futures will be more ergonomic to use with time. For example, instead of having
|
I'll leave you with some suggestions for exercises if you want to explore a little further below.
|
||||||
to create a `RawWaker` and so on, the `Waker` will also be possible to implement
|
|
||||||
as a normal `Trait`. It's probably going to be pretty similar to
|
|
||||||
[ArcWake][arcwake].
|
|
||||||
|
|
||||||
There will probably be several more improvements like this, but since relatively
|
Until next time!
|
||||||
few people will actually need implement leaf Futures compared to those that use
|
|
||||||
them, focus will first and foremost be on how ergonomic it's to work with
|
|
||||||
futures inside async/await functions and blocks.
|
|
||||||
|
|
||||||
It will still take some time for the ecosystem to migrate over to `Futures 3.0`
|
## Reader exercises
|
||||||
but since the advantages are so huge, it will not be a split between libraries
|
|
||||||
using `Futures 1.0` and libraries using `Futures 3.0` for long.
|
|
||||||
|
|
||||||
# Reader exercises
|
So our implementation has taken some obvious shortcuts and could use some improvement.
|
||||||
|
Actually digging into the code and try things yourself is a good way to learn. Here are
|
||||||
|
some good exercises if you want to explore more:
|
||||||
|
|
||||||
So our implementation has taken some obvious shortcuts and could use some improvement. Actually digging into the code and try things yourself is a good
|
### Avoid `thread::park`
|
||||||
way to learn. Here are some good exercises if you want to explore more:
|
|
||||||
|
|
||||||
## Avoid `thread::park`
|
The big problem using `Thread::park` and `Thread::unpark` is that the user can access these
|
||||||
|
same methods from their own code. Try to use another method to suspend our thread and wake
|
||||||
The big problem using `Thread::park` and `Thread::unpark` is that the user can access these same methods from their own code. Try to use another method to
|
it up again on our command. Some hints:
|
||||||
suspend our thread and wake it up again on our command. Some hints:
|
|
||||||
|
|
||||||
* Check out `CondVars`, here are two sources [Wikipedia][condvar_wiki] and the
|
* Check out `CondVars`, here are two sources [Wikipedia][condvar_wiki] and the
|
||||||
docs for [`CondVar`][condvar_std]
|
docs for [`CondVar`][condvar_std]
|
||||||
* Take a look at crates that help you with this exact problem like [Crossbeam ](https://github.com/crossbeam-rs/crossbeam)\(specifically the [`Parker`](https://docs.rs/crossbeam/0.7.3/crossbeam/sync/struct.Parker.html)\)
|
* Take a look at crates that help you with this exact problem like [Crossbeam ](https://github.com/crossbeam-rs/crossbeam)\(specifically the [`Parker`](https://docs.rs/crossbeam/0.7.3/crossbeam/sync/struct.Parker.html)\)
|
||||||
|
|
||||||
## Avoid wrapping the whole `Reactor` in a mutex and pass it around
|
### Avoid wrapping the whole `Reactor` in a mutex and pass it around
|
||||||
|
|
||||||
First of all, protecting the whole `Reactor` and passing it around is overkill. We're only interested in synchronizing some parts of the information it contains. Try to refactor that out and only synchronize access to what's really needed.
|
First of all, protecting the whole `Reactor` and passing it around is overkill. We're only
|
||||||
|
interested in synchronizing some parts of the information it contains. Try to refactor that
|
||||||
|
out and only synchronize access to what's really needed.
|
||||||
|
|
||||||
|
I'd encourage you to have a look at how [the async_std driver is implemented](https://github.com/async-rs/async-std/blob/master/src/net/driver/mod.rs)
|
||||||
|
and [how tokios scheduler is implemented](https://github.com/tokio-rs/tokio/blob/master/tokio/src/runtime/basic_scheduler.rs) to get some inspiration.
|
||||||
|
|
||||||
* Do you want to pass around a reference to this information using an `Arc`?
|
* Do you want to pass around a reference to this information using an `Arc`?
|
||||||
* Do you want to make a global `Reactor` so it can be accessed from anywhere?
|
* Do you want to make a global `Reactor` so it can be accessed from anywhere?
|
||||||
|
|
||||||
Next , using a `Mutex` as a synchronization mechanism might be overkill since many methods only reads data.
|
### Building a better exectuor
|
||||||
|
|
||||||
* Could an [`RwLock`](https://doc.rust-lang.org/stable/std/sync/struct.RwLock.html) be more efficient some places?
|
|
||||||
* Could you use any of the synchronization mechanisms in [Crossbeam](https://github.com/crossbeam-rs/crossbeam)?
|
|
||||||
* Do you want to dig into [atomics in Rust and implement a synchronization mechanism](https://cfsamsonbooks.gitbook.io/epoll-kqueue-iocp-explained/appendix-1/atomics-in-rust) of your own?
|
|
||||||
|
|
||||||
## Avoid creating a new Waker for every event
|
|
||||||
|
|
||||||
Right now we create a new instance of a Waker for every event we create. Is this really needed?
|
|
||||||
|
|
||||||
* Could we create one instance and then cache it \(see [this article from `u/sjepang`](https://stjepang.github.io/2020/01/25/build-your-own-block-on.html)\)?
|
|
||||||
* Should we cache it in `thread_local!` storage?
|
|
||||||
* Or should be cache it using a global constant?
|
|
||||||
|
|
||||||
## Could we implement more methods on our executor?
|
|
||||||
|
|
||||||
What about CPU intensive tasks? Right now they'll prevent our executor thread from progressing an handling events. Could you create a thread pool and create a method to send such tasks to the thread pool instead together with a Waker which will wake up the executor thread once the CPU intensive task is done?
|
|
||||||
|
|
||||||
In both `async_std` and `tokio` this method is called `spawn_blocking`, a good place to start is to read the documentation and the code thy use to implement that.
|
|
||||||
|
|
||||||
## Building a better exectuor
|
|
||||||
|
|
||||||
Right now, we can only run one and one future. Most runtimes has a `spawn`
|
Right now, we can only run one and one future. Most runtimes has a `spawn`
|
||||||
function which let's you start off a future and `await` it later so you
|
function which let's you start off a future and `await` it later so you
|
||||||
can run multiple futures concurrently.
|
can run multiple futures concurrently.
|
||||||
|
|
||||||
As I'm writing this [@stjepan](https://github.com/stjepang) is writing a blog
|
As I suggested in the start of this book, visiting [@stjepan'sblog series about implementing your own executors](https://stjepang.github.io/2020/01/31/build-your-own-executor.html)
|
||||||
series about implementing your own executors, and he just released a post
|
is the place I would start and take it from there.
|
||||||
on how to accomplish just this you can visit [here](https://stjepang.github.io/2020/01/31/build-your-own-executor.html).
|
|
||||||
He knows what he's talking about so I recommend following that.
|
|
||||||
|
|
||||||
In the [bonus_spawn](https://github.com/cfsamson/examples-futures/tree/bonus_spawn)
|
|
||||||
branch of the example repository you can also find an extremely simplified
|
|
||||||
(and worse) way of accomplishing the same in only a few lines of code.
|
|
||||||
|
|
||||||
## Further reading
|
## Further reading
|
||||||
|
|
||||||
There are many great resources for further study. In addition to the RFCs and
|
There are many great resources. In addition to the RFCs and articles I've already
|
||||||
articles I've already linked to in the book, here are some of my suggestions:
|
linked to in the book, here are some of my suggestions:
|
||||||
|
|
||||||
[The official Asyc book](https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html)
|
[The official Asyc book](https://rust-lang.github.io/async-book/01_getting_started/01_chapter.html)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
/* Atelier-Dune Comment */
|
/* Atelier-Dune Comment */
|
||||||
.hljs-comment {
|
.hljs-comment {
|
||||||
color: rgb(68, 68, 68);;
|
color: rgb(160, 160, 160);;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
.hljs-quote {
|
.hljs-quote {
|
||||||
|
|||||||
Reference in New Issue
Block a user