spellcheck intro + 3 first chapters

This commit is contained in:
Carl Fredrik Samson
2020-02-02 18:54:28 +01:00
parent 2d8465e9d1
commit 49fe0ad893
17 changed files with 106 additions and 83 deletions

View File

@@ -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="1_background_information.html" class="active"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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="1_background_information.html" class="active"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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>

View File

@@ -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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html" class="active"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html" class="active"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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>

View File

@@ -3,7 +3,7 @@
<head> <head>
<!-- Book generated using mdBook --> <!-- Book generated using mdBook -->
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Generators and Pin - Futures Explained in 200 Lines of Rust</title> <title>Generators - 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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html" class="active"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html" class="active"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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>
@@ -211,7 +211,7 @@ a callback-based approach, where each closure stores all the data it needs
for computation. This means that as we chain these, the memory required to store for computation. This means that as we chain these, the memory required to store
the needed state increases with each added step.</p> the needed state increases with each added step.</p>
<h3><a class="header" href="#stackless-coroutinesgenerators" id="stackless-coroutinesgenerators">Stackless coroutines/generators</a></h3> <h3><a class="header" href="#stackless-coroutinesgenerators" id="stackless-coroutinesgenerators">Stackless coroutines/generators</a></h3>
<p>This is the model used in Rust today. It a few notable advantages:</p> <p>This is the model used in Rust today. It has a few notable advantages:</p>
<ol> <ol>
<li>It's easy to convert normal Rust code to a stackless coroutine using using <li>It's easy to convert normal Rust code to a stackless coroutine using using
async/await as keywords (it can even be done using a macro).</li> async/await as keywords (it can even be done using a macro).</li>
@@ -404,7 +404,7 @@ impl Generator for GeneratorA {
<p>If you try to compile this you'll get an error (just try it yourself by pressing play).</p> <p>If you try to compile this you'll get an error (just try it yourself by pressing play).</p>
<p>What is the lifetime of <code>&amp;String</code>. It's not the same as the lifetime of <code>Self</code>. It's not <code>static</code>. <p>What is the lifetime of <code>&amp;String</code>. It's not the same as the lifetime of <code>Self</code>. It's not <code>static</code>.
Turns out that it's not possible for us in Rusts syntax to describe this lifetime, which means, that Turns out that it's not possible for us in Rusts syntax to describe this lifetime, which means, that
to make this work, we'll have to let the compiler know that <em>we</em> control this correct.</p> to make this work, we'll have to let the compiler know that <em>we</em> control this correctly ourselves.</p>
<p>That means turning to unsafe.</p> <p>That means turning to unsafe.</p>
<p>Let's try to write an implementation that will compiler using <code>unsafe</code>. As you'll <p>Let's try to write an implementation that will compiler using <code>unsafe</code>. As you'll
see we end up in a <em>self referential struct</em>. A struct which holds references see we end up in a <em>self referential struct</em>. A struct which holds references
@@ -467,7 +467,7 @@ impl Generator for GeneratorA {
let borrowed = &amp;to_borrow; let borrowed = &amp;to_borrow;
let res = borrowed.len(); let res = borrowed.len();
// Tricks to actually get a self reference // Trick to actually get a self reference
*self = GeneratorA::Yield1 {to_borrow, borrowed: std::ptr::null()}; *self = GeneratorA::Yield1 {to_borrow, borrowed: std::ptr::null()};
match self { match self {
GeneratorA::Yield1{to_borrow, borrowed} =&gt; *borrowed = to_borrow, GeneratorA::Yield1{to_borrow, borrowed} =&gt; *borrowed = to_borrow,
@@ -489,10 +489,10 @@ impl Generator for GeneratorA {
} }
</code></pre></pre> </code></pre></pre>
<blockquote> <blockquote>
<p>Try to uncomment the line with <code>mem::swap</code> and see the result of running this code.</p> <p>Try to uncomment the line with <code>mem::swap</code> and see the results.</p>
</blockquote> </blockquote>
<p>While the example above compiles just fine, we expose users of this code to <p>While the example above compiles just fine, we expose consumers of this this API
both possible undefined behavior and other memory errors while using just safe to both possible undefined behavior and other memory errors while using just safe
Rust. This is a big problem!</p> Rust. This is a big problem!</p>
<p>But now, let's prevent the segfault from happening using <code>Pin</code>. We'll discuss <p>But now, let's prevent the segfault from happening using <code>Pin</code>. We'll discuss
<code>Pin</code> more below, but you'll get an introduction here by just reading the <code>Pin</code> more below, but you'll get an introduction here by just reading the
@@ -608,15 +608,16 @@ impl Generator for GeneratorA {
} }
} }
</code></pre></pre> </code></pre></pre>
<p>Now, as you see, the user of this code must either:</p> <p>Now, as you see, the consumer of this API must either:</p>
<ol> <ol>
<li>Box the value and thereby allocating it on the heap</li> <li>Box the value and thereby allocating it on the heap</li>
<li>Use <code>unsafe</code> and pin the value to the stack. The user knows that if they move <li>Use <code>unsafe</code> and pin the value to the stack. The user knows that if they move
the value afterwards it will violate the guarantee they promise to uphold when the value afterwards it will violate the guarantee they promise to uphold when
they did their unsafe implementation.</li> they did their unsafe implementation.</li>
</ol> </ol>
<p>Now, the code which is created and the need for <code>Pin</code> to allow for borrowing <p>Hopefully, after this you'll have an idea of what happens when you use the
across <code>yield</code> points should be pretty clear.</p> <code>yield</code> or <code>await</code> keyword (inside an async function) why we need <code>Pin</code> if we
want to be able to borrow across <code>yield/await</code> points.</p>
</main> </main>

View File

@@ -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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html" class="active"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html" class="active"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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>
@@ -199,7 +199,7 @@ Moving such a type can cause the universe to crash. As of the time of writing
this book, creating an reading fields of a self referential struct still requires <code>unsafe</code>.</p> this book, creating an reading fields of a self referential struct still requires <code>unsafe</code>.</p>
</li> </li>
<li> <li>
<p>You're not really meant to be implementing <code>MustStay</code>, but you can on nightly with a feature flag, or by adding <code>std::marker::PhantomPinned</code> to your type.</p> <p>You can add a <code>MustStay</code> bound on a type by nightly with a feature flag, or by adding <code>std::marker::PhantomPinned</code> to your type.</p>
</li> </li>
<li> <li>
<p>When Pinning, you can either pin a value to memory either on the stack or <p>When Pinning, you can either pin a value to memory either on the stack or

View File

@@ -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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html" class="active"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html" class="active"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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>
@@ -523,8 +523,8 @@ fn main() {
// - first parameter is the `reactor` // - first parameter is the `reactor`
// - the second is a timeout in seconds // - the second is a timeout in seconds
// - the third is an `id` to identify the task // - the third is an `id` to identify the task
let future1 = Task::new(reactor.clone(), 2, 1); let future1 = Task::new(reactor.clone(), 1, 1);
let future2 = Task::new(reactor.clone(), 1, 2); let future2 = Task::new(reactor.clone(), 2, 2);
// an `async` block works the same way as an `async fn` in that it compiles // an `async` block works the same way as an `async fn` in that it compiles
// our code into a state machine, `yielding` at every `await` point. // our code into a state machine, `yielding` at every `await` point.

View File

@@ -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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html" class="active"><strong aria-hidden="true">6.</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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html" class="active"><strong aria-hidden="true">6.</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>
@@ -165,8 +165,12 @@ fn main() {
let reactor = Reactor::new(); let reactor = Reactor::new();
let reactor = Arc::new(Mutex::new(reactor)); let reactor = Arc::new(Mutex::new(reactor));
let future1 = Task::new(reactor.clone(), 2, 1); let future1 = Task::new(reactor.clone(), 1, 1);
let future2 = Task::new(reactor.clone(), 1, 2);
let future2 = Task::new(reactor.clone(), 2, 2);
let fut1 = async { let fut1 = async {
let val = future1.await; let val = future1.await;

View File

@@ -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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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>

View File

@@ -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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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>

View File

@@ -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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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>

View File

@@ -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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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="1_background_information.html"><strong aria-hidden="true">1.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">2.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">3.</strong> Generators</a></li><li><a href="4_pin.html"><strong aria-hidden="true">4.</strong> Pin</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">5.</strong> The main example</a></li><li><a href="8_finished_example.html"><strong aria-hidden="true">6.</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>
@@ -455,7 +455,7 @@ a callback-based approach, where each closure stores all the data it needs
for computation. This means that as we chain these, the memory required to store for computation. This means that as we chain these, the memory required to store
the needed state increases with each added step.</p> the needed state increases with each added step.</p>
<h3><a class="header" href="#stackless-coroutinesgenerators" id="stackless-coroutinesgenerators">Stackless coroutines/generators</a></h3> <h3><a class="header" href="#stackless-coroutinesgenerators" id="stackless-coroutinesgenerators">Stackless coroutines/generators</a></h3>
<p>This is the model used in Rust today. It a few notable advantages:</p> <p>This is the model used in Rust today. It has a few notable advantages:</p>
<ol> <ol>
<li>It's easy to convert normal Rust code to a stackless coroutine using using <li>It's easy to convert normal Rust code to a stackless coroutine using using
async/await as keywords (it can even be done using a macro).</li> async/await as keywords (it can even be done using a macro).</li>
@@ -648,7 +648,7 @@ impl Generator for GeneratorA {
<p>If you try to compile this you'll get an error (just try it yourself by pressing play).</p> <p>If you try to compile this you'll get an error (just try it yourself by pressing play).</p>
<p>What is the lifetime of <code>&amp;String</code>. It's not the same as the lifetime of <code>Self</code>. It's not <code>static</code>. <p>What is the lifetime of <code>&amp;String</code>. It's not the same as the lifetime of <code>Self</code>. It's not <code>static</code>.
Turns out that it's not possible for us in Rusts syntax to describe this lifetime, which means, that Turns out that it's not possible for us in Rusts syntax to describe this lifetime, which means, that
to make this work, we'll have to let the compiler know that <em>we</em> control this correct.</p> to make this work, we'll have to let the compiler know that <em>we</em> control this correctly ourselves.</p>
<p>That means turning to unsafe.</p> <p>That means turning to unsafe.</p>
<p>Let's try to write an implementation that will compiler using <code>unsafe</code>. As you'll <p>Let's try to write an implementation that will compiler using <code>unsafe</code>. As you'll
see we end up in a <em>self referential struct</em>. A struct which holds references see we end up in a <em>self referential struct</em>. A struct which holds references
@@ -711,7 +711,7 @@ impl Generator for GeneratorA {
let borrowed = &amp;to_borrow; let borrowed = &amp;to_borrow;
let res = borrowed.len(); let res = borrowed.len();
// Tricks to actually get a self reference // Trick to actually get a self reference
*self = GeneratorA::Yield1 {to_borrow, borrowed: std::ptr::null()}; *self = GeneratorA::Yield1 {to_borrow, borrowed: std::ptr::null()};
match self { match self {
GeneratorA::Yield1{to_borrow, borrowed} =&gt; *borrowed = to_borrow, GeneratorA::Yield1{to_borrow, borrowed} =&gt; *borrowed = to_borrow,
@@ -733,10 +733,10 @@ impl Generator for GeneratorA {
} }
</code></pre></pre> </code></pre></pre>
<blockquote> <blockquote>
<p>Try to uncomment the line with <code>mem::swap</code> and see the result of running this code.</p> <p>Try to uncomment the line with <code>mem::swap</code> and see the results.</p>
</blockquote> </blockquote>
<p>While the example above compiles just fine, we expose users of this code to <p>While the example above compiles just fine, we expose consumers of this this API
both possible undefined behavior and other memory errors while using just safe to both possible undefined behavior and other memory errors while using just safe
Rust. This is a big problem!</p> Rust. This is a big problem!</p>
<p>But now, let's prevent the segfault from happening using <code>Pin</code>. We'll discuss <p>But now, let's prevent the segfault from happening using <code>Pin</code>. We'll discuss
<code>Pin</code> more below, but you'll get an introduction here by just reading the <code>Pin</code> more below, but you'll get an introduction here by just reading the
@@ -852,15 +852,16 @@ impl Generator for GeneratorA {
} }
} }
</code></pre></pre> </code></pre></pre>
<p>Now, as you see, the user of this code must either:</p> <p>Now, as you see, the consumer of this API must either:</p>
<ol> <ol>
<li>Box the value and thereby allocating it on the heap</li> <li>Box the value and thereby allocating it on the heap</li>
<li>Use <code>unsafe</code> and pin the value to the stack. The user knows that if they move <li>Use <code>unsafe</code> and pin the value to the stack. The user knows that if they move
the value afterwards it will violate the guarantee they promise to uphold when the value afterwards it will violate the guarantee they promise to uphold when
they did their unsafe implementation.</li> they did their unsafe implementation.</li>
</ol> </ol>
<p>Now, the code which is created and the need for <code>Pin</code> to allow for borrowing <p>Hopefully, after this you'll have an idea of what happens when you use the
across <code>yield</code> points should be pretty clear.</p> <code>yield</code> or <code>await</code> keyword (inside an async function) why we need <code>Pin</code> if we
want to be able to borrow across <code>yield/await</code> points.</p>
<h1><a class="header" href="#pin" id="pin">Pin</a></h1> <h1><a class="header" href="#pin" id="pin">Pin</a></h1>
<blockquote> <blockquote>
<p><strong>Relevant for</strong></p> <p><strong>Relevant for</strong></p>
@@ -911,7 +912,7 @@ Moving such a type can cause the universe to crash. As of the time of writing
this book, creating an reading fields of a self referential struct still requires <code>unsafe</code>.</p> this book, creating an reading fields of a self referential struct still requires <code>unsafe</code>.</p>
</li> </li>
<li> <li>
<p>You're not really meant to be implementing <code>MustStay</code>, but you can on nightly with a feature flag, or by adding <code>std::marker::PhantomPinned</code> to your type.</p> <p>You can add a <code>MustStay</code> bound on a type by nightly with a feature flag, or by adding <code>std::marker::PhantomPinned</code> to your type.</p>
</li> </li>
<li> <li>
<p>When Pinning, you can either pin a value to memory either on the stack or <p>When Pinning, you can either pin a value to memory either on the stack or
@@ -1504,8 +1505,8 @@ fn main() {
// - first parameter is the `reactor` // - first parameter is the `reactor`
// - the second is a timeout in seconds // - the second is a timeout in seconds
// - the third is an `id` to identify the task // - the third is an `id` to identify the task
let future1 = Task::new(reactor.clone(), 2, 1); let future1 = Task::new(reactor.clone(), 1, 1);
let future2 = Task::new(reactor.clone(), 1, 2); let future2 = Task::new(reactor.clone(), 2, 2);
// an `async` block works the same way as an `async fn` in that it compiles // an `async` block works the same way as an `async fn` in that it compiles
// our code into a state machine, `yielding` at every `await` point. // our code into a state machine, `yielding` at every `await` point.
@@ -1802,8 +1803,12 @@ fn main() {
let reactor = Reactor::new(); let reactor = Reactor::new();
let reactor = Arc::new(Mutex::new(reactor)); let reactor = Arc::new(Mutex::new(reactor));
let future1 = Task::new(reactor.clone(), 2, 1); let future1 = Task::new(reactor.clone(), 1, 1);
let future2 = Task::new(reactor.clone(), 1, 2);
let future2 = Task::new(reactor.clone(), 2, 2);
let fut1 = async { let fut1 = async {
let val = future1.await; let val = future1.await;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -3,9 +3,8 @@
> **Relevant for:** > **Relevant for:**
> >
> - High level introduction to concurrency in Rust > - High level introduction to concurrency in Rust
> - Knowing what Rust provides and not when working with async > - Knowing what Rust provides and not when working with async code
> - Understanding why we need runtimes > - Understanding why we need runtimes
> - Knowing that Rust has `Futures 1.0` and `Futures 3.0`, and how to deal with them
> - Getting pointers to further reading on concurrency in general > - Getting pointers to further reading on concurrency in general
Before we start implementing our `Futures` , we'll go through some background Before we start implementing our `Futures` , we'll go through some background
@@ -21,15 +20,17 @@ Let's get some of the common roadblocks out of the way first.
Async in Rust is different from most other languages in the sense that Rust Async in Rust is different from most other languages in the sense that Rust
has a very lightweight runtime. has a very lightweight runtime.
In languages like C#, JavaScript, Java and GO, already includes a runtime Languages like C#, JavaScript, Java and GO, already includes a runtime
for handling concurrency. So if you come from one of those languages this will for handling concurrency. So if you come from one of those languages this will
seem a bit strange to you. seem a bit strange to you.
In Rust you will have to make an active choice about which runtime to use.
### What Rust's standard library takes care of ### What Rust's standard library takes care of
1. The definition of an interruptible task 1. The definition of an interruptible task
2. An efficient technique to start, suspend, resume and store tasks 2. An efficient technique to start, suspend, resume and store tasks which are
which are executed concurrently. executed concurrently.
3. A defined way to wake up a suspended task 3. A defined way to wake up a suspended task
That's really what Rusts standard library does. As you see there is no definition That's really what Rusts standard library does. As you see there is no definition
@@ -48,18 +49,19 @@ an event queue and so on.
Executors, accepts one or more asynchronous tasks called `Futures` and takes Executors, accepts one or more asynchronous tasks called `Futures` and takes
care of actually running the code we write, suspend the tasks when they're care of actually running the code we write, suspend the tasks when they're
waiting for I/O and resumes them. waiting for I/O and resume them.
In theory, we could choose one `Reactor` and one `Executor` that have nothing In theory, we could choose one `Reactor` and one `Executor` that have nothing
to do with each other besides one creates leaf `Futures` and one runs them, but to do with each other besides that one creates leaf `Futures` and the other one
in reality today you'll most often get both in a `Runtime`. runs them, but in reality today you'll most often get both in a `Runtime`.
There are mainly two such runtimes today [async_std][async_std] and [tokio][tokio]. There are mainly two such runtimes today [async_std][async_std] and [tokio][tokio].
Quite a bit of complexity attributed to `Futures` are actually complexity rooted Quite a bit of complexity attributed to `Futures` are actually complexity rooted
in runtimes. Creating an efficient runtime is hard. Learning how to use one in runtimes. Creating an efficient runtime is hard.
correctly can be hard as well, but both are excellent and it's just like
learning any new library. Learning how to use one correctly can require quite a bit of effort as well, but you'll see that there are several similarities between these kind of runtimes so
learning one makes learning the next much easier.
The difference between Rust and other languages is that you have to make an The difference between Rust and other languages is that you have to make an
active choice when it comes to picking a runtime. Most often you'll just use active choice when it comes to picking a runtime. Most often you'll just use
@@ -80,9 +82,10 @@ to know in advance.
A good sign is that if you're required to use combinators like `and_then` then A good sign is that if you're required to use combinators like `and_then` then
you're using `Futures 1.0`. you're using `Futures 1.0`.
While not directly compatible, there is a tool that let's you relatively easily While they're not directly compatible, there is a tool that let's you relatively
convert a `Future 1.0` to a `Future 3.0` and vice a versa. You can find all you easily convert a `Future 1.0` to a `Future 3.0` and vice a versa. You can find
need in the [`futures-rs`][futures_rs] crate and all [information you need here][compat_info]. all you need in the [`futures-rs`][futures_rs] crate and all
[information you need here][compat_info].
## First things first ## First things first
@@ -96,13 +99,12 @@ try to give a high level overview that will make it easier to learn Rusts
* [Async Basics - Strategies for handling I/O](https://cfsamson.github.io/book-exploring-async-basics/5_strategies_for_handling_io.html) * [Async Basics - Strategies for handling I/O](https://cfsamson.github.io/book-exploring-async-basics/5_strategies_for_handling_io.html)
* [Async Basics - Epoll, Kqueue and IOCP](https://cfsamson.github.io/book-exploring-async-basics/6_epoll_kqueue_iocp.html) * [Async Basics - Epoll, Kqueue and IOCP](https://cfsamson.github.io/book-exploring-async-basics/6_epoll_kqueue_iocp.html)
Now learning these concepts by studying futures is making it much harder than Learning these concepts by studying futures is making it much harder than
it needs to be, so go on and read these chapters. I'll be right here when it needs to be, so go on and read these chapters if you feel a bit unsure.
you're back.
However, if you feel that you have the basics covered, then go right on. I'll be right here when you're back.
Let's get moving! However, if you feel that you have the basics covered, then let's get moving!
[async_std]: https://github.com/async-rs/async-std [async_std]: https://github.com/async-rs/async-std
[tokio]: https://github.com/tokio-rs/tokio [tokio]: https://github.com/tokio-rs/tokio

View File

@@ -8,7 +8,7 @@
## Trait objects and dynamic dispatch ## Trait objects and dynamic dispatch
One of the most confusing topic we encounter when implementing our own `Futures` One of the most confusing things we encounter when implementing our own `Futures`
is how we implement a `Waker` . Creating a `Waker` involves creating a `vtable` is how we implement a `Waker` . Creating a `Waker` involves creating a `vtable`
which allows us to use dynamic dispatch to call methods on a _type erased_ trait which allows us to use dynamic dispatch to call methods on a _type erased_ trait
object we construct our selves. object we construct our selves.
@@ -44,7 +44,7 @@ As you see from the output after running this, the sizes of the references varie
Many are 8 bytes (which is a pointer size on 64 bit systems), but some are 16 Many are 8 bytes (which is a pointer size on 64 bit systems), but some are 16
bytes. bytes.
The 16 byte sized pointers are called "fat pointers" since they carry more extra The 16 byte sized pointers are called "fat pointers" since they carry extra
information. information.
**Example `&[i32]` :** **Example `&[i32]` :**
@@ -55,7 +55,7 @@ information.
**Example `&dyn SomeTrait`:** **Example `&dyn SomeTrait`:**
This is the type of fat pointer we'll concern ourselves about going forward. This is the type of fat pointer we'll concern ourselves about going forward.
`&dyn SomeTrait` is a reference to a trait, or what Rust calls _trait objects_. `&dyn SomeTrait` is a reference to a trait, or what Rust calls a _trait object_.
The layout for a pointer to a _trait object_ looks like this: The layout for a pointer to a _trait object_ looks like this:
@@ -63,7 +63,7 @@ The layout for a pointer to a _trait object_ looks like this:
- The second 8 bytes points to the `vtable` for the trait object - The second 8 bytes points to the `vtable` for the trait object
The reason for this is to allow us to refer to an object we know nothing about The reason for this is to allow us to refer to an object we know nothing about
except that it implements the methods defined by our trait. To allow accomplish this we use _dynamic dispatch_. except that it implements the methods defined by our trait. To accomplish this we use _dynamic dispatch_.
Let's explain this in code instead of words by implementing our own trait Let's explain this in code instead of words by implementing our own trait
object from these parts: object from these parts:

View File

@@ -3,21 +3,20 @@
>**Relevant for:** >**Relevant for:**
> >
>- Understanding how the async/await syntax works since it's how `await` is implemented >- Understanding how the async/await syntax works since it's how `await` is implemented
>- Why we need `Pin` >- Knowing why we need `Pin`
>- Why Rusts async model is very efficient >- Understanding why Rusts async model is very efficient
> >
>The motivation for `Generators` can be found in [RFC#2033][rfc2033]. It's very >The motivation for `Generators` can be found in [RFC#2033][rfc2033]. It's very
>well written and I can recommend reading through it (it talks as much about >well written and I can recommend reading through it (it talks as much about
>async/await as it does about generators). >async/await as it does about generators).
The second difficult part that there seems to be a lot of questions about The second difficult part is understanding Generators and the `Pin` type. Since
is Generators and the `Pin` type. Since they're related we'll start off by they're related we'll start off by exploring generators first. By doing that
exploring generators first. By doing that we'll soon get to see why we'll soon get to see why we need to be able to "pin" some data to a fixed
we need to be able to "pin" some data to a fixed location in memory and location in memory and get an introduction to `Pin` as well.
get an introduction to `Pin` as well.
Basically, there were three main options that were discussed when Rust was Basically, there were three main options discussed when designing how Rust would
designing how the language would handle concurrency: handle concurrency:
1. Stackful coroutines, better known as green threads. 1. Stackful coroutines, better known as green threads.
2. Using combinators. 2. Using combinators.
@@ -29,9 +28,11 @@ I've written about green threads before. Go check out
[Green Threads Explained in 200 lines of Rust][greenthreads] if you're interested. [Green Threads Explained in 200 lines of Rust][greenthreads] if you're interested.
Green threads uses the same mechanisms as an OS does by creating a thread for Green threads uses the same mechanisms as an OS does by creating a thread for
each task, setting up a stack, save the CPU's state and jump each task, setting up a stack, save the CPU's state and jump from one
from one task(thread) to another by doing a "context switch". We yield control to the scheduler which then task(thread) to another by doing a "context switch".
continues running a different task.
We yield control to the scheduler (which is a central part of the runtime in
such a system) which then continues running a different task.
Rust had green threads once, but they were removed before it hit 1.0. The state Rust had green threads once, but they were removed before it hit 1.0. The state
of execution is stored in each stack so in such a solution there would be no need of execution is stored in each stack so in such a solution there would be no need

View File

@@ -72,8 +72,15 @@ There are many great resources for further study. In addition to the RFCs and
articles I've already linked to in the book, here are some of my suggestions: articles I've already 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)
[The async_std book](https://book.async.rs/) [The async_std book](https://book.async.rs/)
[Aron Turon: Designing futures for Rust](https://aturon.github.io/blog/2016/09/07/futures-design/) [Aron Turon: Designing futures for Rust](https://aturon.github.io/blog/2016/09/07/futures-design/)
[Steve Klabnik's presentation: Rust's journey to Async/Await](https://www.infoq.com/presentations/rust-2019/) [Steve Klabnik's presentation: Rust's journey to Async/Await](https://www.infoq.com/presentations/rust-2019/)
[The Tokio Blog](https://tokio.rs/blog/2019-10-scheduler/) [The Tokio Blog](https://tokio.rs/blog/2019-10-scheduler/)
[Stjepan's blog with a series where he implements an Executor](https://stjepang.github.io/) [Stjepan's blog with a series where he implements an Executor](https://stjepang.github.io/)
[Jon Gjengset's video on The Why, What and How of Pinning in Rust](https://youtu.be/DkMwYxfSYNQ)

View File

@@ -8,7 +8,7 @@ The goal is to get a better understanding of `Futures` by implementing a toy
We'll start off a bit differently than most other explanations. Instead of We'll start off a bit differently than most other explanations. Instead of
deferring some of the details about what's special about futures in Rust we deferring some of the details about what's special about futures in Rust we
try to tackle that head on first. We'll be as brief as possible, but as thorough try to tackle that head on first. We'll be as brief as possible, but as thorough
as needed. This way, most question will be answered and explored up front. as needed. This way, most questions will be answered and explored up front.
We'll end up with futures that can run an any executor like `tokio` and `async_str`. We'll end up with futures that can run an any executor like `tokio` and `async_str`.
@@ -27,8 +27,11 @@ of all, this book will focus on `Futures` and `async/await` specifically and
not in the context of any specific runtime. not in the context of any specific runtime.
Secondly, I've always found small runnable examples very exiting to learn from. Secondly, I've always found small runnable examples very exiting to learn from.
Thanks to [Mdbook][mdbook] the examples can even be edited and explored further. It's Thanks to [Mdbook][mdbook] the examples can even be edited and explored further
all code that you can download, play with and learn from. by uncommenting certain lines or adding new ones yourself. I use that quite a
but throughout so keep an eye out when reading through editable code segments.
It's all code that you can download, play with and learn from.
We'll and end up with an understandable example including a `Future` We'll and end up with an understandable example including a `Future`
implementation, an `Executor` and a `Reactor` in less than 200 lines of code. implementation, an `Executor` and a `Reactor` in less than 200 lines of code.