added last chapter
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><a href="0_0_introduction.html" class="active"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html" class="active"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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>
|
||||||
@@ -182,7 +182,7 @@ way that mortal people can understand, and that requires a lot of work. So thank
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a rel="next" href="1_0_background_information.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a rel="next" href="1_background_information.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ way that mortal people can understand, and that requires a lot of work. So thank
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="1_0_background_information.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a href="1_background_information.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -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><a href="0_0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html" class="active"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html" class="active"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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>
|
||||||
@@ -232,13 +232,13 @@ you're back. </p>
|
|||||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
<!-- Mobile navigation buttons -->
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
<a rel="prev" href="0_0_introduction.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a rel="prev" href="0_introduction.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a rel="next" href="1_1_trait_objects.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a rel="next" href="2_trait_objects.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -250,13 +250,13 @@ you're back. </p>
|
|||||||
|
|
||||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
|
|
||||||
<a href="0_0_introduction.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a href="0_introduction.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="1_1_trait_objects.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a href="2_trait_objects.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -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><a href="0_0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html" class="active"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html" class="active"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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>
|
||||||
@@ -278,13 +278,13 @@ it is will make this much less mysterious.</p>
|
|||||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
<!-- Mobile navigation buttons -->
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
<a rel="prev" href="1_0_background_information.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a rel="prev" href="1_background_information.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a rel="next" href="1_2_generators_pin.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a rel="next" href="3_generators_pin.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -296,13 +296,13 @@ it is will make this much less mysterious.</p>
|
|||||||
|
|
||||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
|
|
||||||
<a href="1_0_background_information.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a href="1_background_information.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="1_2_generators_pin.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a href="3_generators_pin.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -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><a href="0_0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html" class="active"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html" class="active"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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>
|
||||||
@@ -295,7 +295,7 @@ impl Generator for GeneratorA {
|
|||||||
match std::mem::replace(&mut *self, GeneratorA::Exit) {
|
match std::mem::replace(&mut *self, GeneratorA::Exit) {
|
||||||
GeneratorA::Enter(a1) => {
|
GeneratorA::Enter(a1) => {
|
||||||
|
|
||||||
/*|---code before yield1---|*/
|
/*|---code before yield---|*/
|
||||||
/*|*/ println!("Hello"); /*|*/
|
/*|*/ println!("Hello"); /*|*/
|
||||||
/*|*/ let a = a1 * 2; /*|*/
|
/*|*/ let a = a1 * 2; /*|*/
|
||||||
/*|------------------------|*/
|
/*|------------------------|*/
|
||||||
@@ -305,7 +305,7 @@ impl Generator for GeneratorA {
|
|||||||
}
|
}
|
||||||
GeneratorA::Yield1(_) => {
|
GeneratorA::Yield1(_) => {
|
||||||
|
|
||||||
/*|----code after yield1----|*/
|
/*|----code after yield----|*/
|
||||||
/*|*/ println!("world!"); /*|*/
|
/*|*/ println!("world!"); /*|*/
|
||||||
/*|-------------------------|*/
|
/*|-------------------------|*/
|
||||||
|
|
||||||
@@ -316,6 +316,7 @@ impl Generator for GeneratorA {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>The <code>yield</code> keyword was discussed first in <a href="https://github.com/rust-lang/rfcs/pull/1823">RFC#1823</a> and in <a href="https://github.com/rust-lang/rfcs/pull/1832">RFC#1832</a>.</p>
|
<p>The <code>yield</code> keyword was discussed first in <a href="https://github.com/rust-lang/rfcs/pull/1823">RFC#1823</a> and in <a href="https://github.com/rust-lang/rfcs/pull/1832">RFC#1832</a>.</p>
|
||||||
@@ -413,6 +414,7 @@ into itself.</p>
|
|||||||
if let GeneratorState::Yielded(n) = gen.resume() {
|
if let GeneratorState::Yielded(n) = gen.resume() {
|
||||||
println!("Got value {}", n);
|
println!("Got value {}", n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If you uncomment this, very bad things can happen. This is why we need `Pin`
|
// If you uncomment this, very bad things can happen. This is why we need `Pin`
|
||||||
// std::mem::swap(&mut gen, &mut gen2);
|
// std::mem::swap(&mut gen, &mut gen2);
|
||||||
|
|
||||||
@@ -618,13 +620,13 @@ across <code>yield</code> points should be pretty clear. </p>
|
|||||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
<!-- Mobile navigation buttons -->
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
<a rel="prev" href="1_1_trait_objects.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a rel="prev" href="2_trait_objects.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a rel="next" href="1_3_pin.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a rel="next" href="4_pin.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -636,13 +638,13 @@ across <code>yield</code> points should be pretty clear. </p>
|
|||||||
|
|
||||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
|
|
||||||
<a href="1_1_trait_objects.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a href="2_trait_objects.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="1_3_pin.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a href="4_pin.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -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><a href="0_0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html" class="active"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html" class="active"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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>
|
||||||
@@ -278,36 +278,13 @@ with the data stored at the memory location <code>test2</code> is pointing to an
|
|||||||
occupied with the string "test2". This can be a bit hard to visualize so I made
|
occupied with the string "test2". This can be a bit hard to visualize so I made
|
||||||
a figure that i hope can help.</p>
|
a figure that i hope can help.</p>
|
||||||
<p><strong>Fig 1: Before and after swap</strong>
|
<p><strong>Fig 1: Before and after swap</strong>
|
||||||
<img src="../assets/swap_problem.jpg" alt="swap_problem" /></p>
|
<img src="./assets/swap_problem.jpg" alt="swap_problem" /></p>
|
||||||
<p>As you can see this results in unwanted behavior. It's easy to get this to
|
<p>As you can see this results in unwanted behavior. It's easy to get this to
|
||||||
segfault, show UB and fail in other spectacular ways as well.</p>
|
segfault, show UB and fail in other spectacular ways as well.</p>
|
||||||
<p>If we change the example to using <code>Pin</code> instead:</p>
|
<p>If we change the example to using <code>Pin</code> instead:</p>
|
||||||
<pre><pre class="playpen"><code class="language-rust editable">use std::pin::Pin;
|
<pre><pre class="playpen"><code class="language-rust editable">use std::pin::Pin;
|
||||||
use std::marker::PhantomPinned;
|
use std::marker::PhantomPinned;
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
let mut test1 = Test::new("test1");
|
|
||||||
test1.init();
|
|
||||||
let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) };
|
|
||||||
let mut test2 = Test::new("test2");
|
|
||||||
test2.init();
|
|
||||||
let mut test2_pin = unsafe { Pin::new_unchecked(&mut test2) };
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"a: {}, b: {}",
|
|
||||||
Test::a(test1_pin.as_ref()),
|
|
||||||
Test::b(test1_pin.as_ref())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Try to uncomment this and see what happens
|
|
||||||
// std::mem::swap(test1_pin.as_mut(), test2_pin.as_mut());
|
|
||||||
println!(
|
|
||||||
"a: {}, b: {}",
|
|
||||||
Test::a(test2_pin.as_ref()),
|
|
||||||
Test::b(test2_pin.as_ref())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Test {
|
struct Test {
|
||||||
a: String,
|
a: String,
|
||||||
@@ -340,6 +317,29 @@ impl Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut test1 = Test::new("test1");
|
||||||
|
test1.init();
|
||||||
|
let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) };
|
||||||
|
let mut test2 = Test::new("test2");
|
||||||
|
test2.init();
|
||||||
|
let mut test2_pin = unsafe { Pin::new_unchecked(&mut test2) };
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"a: {}, b: {}",
|
||||||
|
Test::a(test1_pin.as_ref()),
|
||||||
|
Test::b(test1_pin.as_ref())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try to uncomment this and see what happens
|
||||||
|
// std::mem::swap(test1_pin.as_mut(), test2_pin.as_mut());
|
||||||
|
println!(
|
||||||
|
"a: {}, b: {}",
|
||||||
|
Test::a(test2_pin.as_ref()),
|
||||||
|
Test::b(test2_pin.as_ref())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
<p>Now, what we've done here is pinning a stack address. That will always be
|
<p>Now, what we've done here is pinning a stack address. That will always be
|
||||||
<code>unsafe</code> if our type implements <code>!Unpin</code> (aka <code>MustStay</code>). </p>
|
<code>unsafe</code> if our type implements <code>!Unpin</code> (aka <code>MustStay</code>). </p>
|
||||||
@@ -354,17 +354,6 @@ any pointers we take to "self" is invalidated.</p>
|
|||||||
<pre><pre class="playpen"><code class="language-rust editbable">use std::pin::Pin;
|
<pre><pre class="playpen"><code class="language-rust editbable">use std::pin::Pin;
|
||||||
use std::marker::PhantomPinned;
|
use std::marker::PhantomPinned;
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
let mut test1 = Test::new("test1");
|
|
||||||
let mut test2 = Test::new("test2");
|
|
||||||
|
|
||||||
println!("a: {}, b: {}",test1.as_ref().a(), test1.as_ref().b());
|
|
||||||
|
|
||||||
// Try to uncomment this and see what happens
|
|
||||||
// std::mem::swap(&mut test1, &mut test2);
|
|
||||||
println!("a: {}, b: {}",test2.as_ref().a(), test2.as_ref().b());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Test {
|
struct Test {
|
||||||
a: String,
|
a: String,
|
||||||
@@ -395,6 +384,17 @@ impl Test {
|
|||||||
unsafe { &*(self.b) }
|
unsafe { &*(self.b) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut test1 = Test::new("test1");
|
||||||
|
let mut test2 = Test::new("test2");
|
||||||
|
|
||||||
|
println!("a: {}, b: {}",test1.as_ref().a(), test1.as_ref().b());
|
||||||
|
|
||||||
|
// Try to uncomment this and see what happens
|
||||||
|
// std::mem::swap(&mut test1, &mut test2);
|
||||||
|
println!("a: {}, b: {}",test2.as_ref().a(), test2.as_ref().b());
|
||||||
|
}
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
<p>The fact that boxing (heap allocating) a value that implements <code>!Unpin</code> is safe
|
<p>The fact that boxing (heap allocating) a value that implements <code>!Unpin</code> is safe
|
||||||
makes sense. Once the data is allocated on the heap it will have a stable address.</p>
|
makes sense. Once the data is allocated on the heap it will have a stable address.</p>
|
||||||
@@ -420,13 +420,13 @@ we're soon finished.</p>
|
|||||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
<!-- Mobile navigation buttons -->
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
<a rel="prev" href="1_2_generators_pin.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a rel="prev" href="3_generators_pin.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a rel="next" href="1_4_reactor_executor.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a rel="next" href="5_reactor_executor.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -438,13 +438,13 @@ we're soon finished.</p>
|
|||||||
|
|
||||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
|
|
||||||
<a href="1_2_generators_pin.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a href="3_generators_pin.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="1_4_reactor_executor.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a href="5_reactor_executor.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -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><a href="0_0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html" class="active"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html" class="active"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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>
|
||||||
@@ -226,13 +226,13 @@ example.</p>
|
|||||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
<!-- Mobile navigation buttons -->
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
<a rel="prev" href="1_3_pin.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a rel="prev" href="4_pin.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a rel="next" href="2_0_future_example.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a rel="next" href="6_future_example.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -244,13 +244,13 @@ example.</p>
|
|||||||
|
|
||||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
|
|
||||||
<a href="1_3_pin.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a href="4_pin.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="2_0_future_example.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a href="6_future_example.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -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><a href="0_0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html" class="active"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html" class="active"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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>
|
||||||
@@ -660,13 +660,13 @@ impl Drop for Reactor {
|
|||||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
<!-- Mobile navigation buttons -->
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
<a rel="prev" href="1_4_reactor_executor.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a rel="prev" href="5_reactor_executor.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a rel="next" href="2_1_concurrent_futures.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a rel="next" href="7_conclusion.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -678,13 +678,13 @@ impl Drop for Reactor {
|
|||||||
|
|
||||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
|
|
||||||
<a href="1_4_reactor_executor.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a href="5_reactor_executor.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="2_1_concurrent_futures.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
<a href="7_conclusion.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
266
book/7_conclusion.html
Normal file
266
book/7_conclusion.html
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html lang="en" class="sidebar-visible no-js">
|
||||||
|
<head>
|
||||||
|
<!-- Book generated using mdBook -->
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Conclusion and exercises - Futures Explained in 200 Lines of Rust</title>
|
||||||
|
|
||||||
|
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="theme-color" content="#ffffff" />
|
||||||
|
|
||||||
|
<link rel="shortcut icon" href="favicon.png">
|
||||||
|
<link rel="stylesheet" href="css/variables.css">
|
||||||
|
<link rel="stylesheet" href="css/general.css">
|
||||||
|
<link rel="stylesheet" href="css/chrome.css">
|
||||||
|
<link rel="stylesheet" href="css/print.css" media="print">
|
||||||
|
|
||||||
|
<!-- Fonts -->
|
||||||
|
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<!-- Highlight.js Stylesheets -->
|
||||||
|
<link rel="stylesheet" href="highlight.css">
|
||||||
|
<link rel="stylesheet" href="tomorrow-night.css">
|
||||||
|
<link rel="stylesheet" href="ayu-highlight.css">
|
||||||
|
|
||||||
|
<!-- Custom theme stylesheets -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="light">
|
||||||
|
<!-- Provide site root to javascript -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var path_to_root = "";
|
||||||
|
var default_theme = "light";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
try {
|
||||||
|
var theme = localStorage.getItem('mdbook-theme');
|
||||||
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||||||
|
|
||||||
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||||||
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||||||
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||||||
|
}
|
||||||
|
} catch (e) { }
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var theme;
|
||||||
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||||
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||||
|
document.body.className = theme;
|
||||||
|
document.querySelector('html').className = theme + ' js';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Hide / unhide sidebar before it is displayed -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var html = document.querySelector('html');
|
||||||
|
var sidebar = 'hidden';
|
||||||
|
if (document.body.clientWidth >= 1080) {
|
||||||
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||||
|
sidebar = sidebar || 'visible';
|
||||||
|
}
|
||||||
|
html.classList.remove('sidebar-visible');
|
||||||
|
html.classList.add("sidebar-" + sidebar);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||||
|
<div class="sidebar-scrollbox">
|
||||||
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html" class="active"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</a></li></ol>
|
||||||
|
</div>
|
||||||
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div id="page-wrapper" class="page-wrapper">
|
||||||
|
|
||||||
|
<div class="page">
|
||||||
|
|
||||||
|
<div id="menu-bar" class="menu-bar">
|
||||||
|
<div id="menu-bar-sticky-container">
|
||||||
|
<div class="left-buttons">
|
||||||
|
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||||
|
<i class="fa fa-bars"></i>
|
||||||
|
</button>
|
||||||
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||||||
|
<i class="fa fa-paint-brush"></i>
|
||||||
|
</button>
|
||||||
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||||||
|
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
|
||||||
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
|
||||||
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||||||
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||||||
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||||||
|
<i class="fa fa-search"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 class="menu-title">Futures Explained in 200 Lines of Rust</h1>
|
||||||
|
|
||||||
|
<div class="right-buttons">
|
||||||
|
<a href="print.html" title="Print this book" aria-label="Print this book">
|
||||||
|
<i id="print-button" class="fa fa-print"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="search-wrapper" class="hidden">
|
||||||
|
<form id="searchbar-outer" class="searchbar-outer">
|
||||||
|
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||||||
|
</form>
|
||||||
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||||||
|
<div id="searchresults-header" class="searchresults-header"></div>
|
||||||
|
<ul id="searchresults">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||||||
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||||||
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||||||
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="content" class="content">
|
||||||
|
<main>
|
||||||
|
<h1><a class="header" href="#conclusion-and-exercises" id="conclusion-and-exercises">Conclusion and exercises</a></h1>
|
||||||
|
<h1><a class="header" href="#reader-excercises" id="reader-excercises">Reader excercises</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 som relatively simple and good exercises:</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 of telling the OS to suspend our thread and wake it up again on our command. Some hints:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Check out <code>CondVars</code>, here are two sources Wikipedia and the docs for <code>CondVar</code></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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<ul>
|
||||||
|
<li>Do you want to pass around a reference to this information using an <code>Arc</code>?</li>
|
||||||
|
<li>Do you want to make this information global so it can be accessed from anywhere?</li>
|
||||||
|
</ul>
|
||||||
|
<p>Next , using a <code>Mutex</code> as a synchronization mechanism might be overkill since many methods only reads data. </p>
|
||||||
|
<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="#further-reading" id="further-reading">Further reading</a></h2>
|
||||||
|
<p>There are many great resources for further study. Here are some of my suggestions:</p>
|
||||||
|
<p>The Asyc book:</p>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
|
<a rel="prev" href="6_future_example.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
|
<i class="fa fa-angle-left"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a rel="next" href="8_concurrent_futures.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
|
<i class="fa fa-angle-right"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="clear: both"></div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
|
|
||||||
|
<a href="6_future_example.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
|
<i class="fa fa-angle-left"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a href="8_concurrent_futures.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||||
|
<i class="fa fa-angle-right"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Livereload script (if served using the cli tool) -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var socket = new WebSocket("ws://localhost:3001");
|
||||||
|
socket.onmessage = function (event) {
|
||||||
|
if (event.data === "reload") {
|
||||||
|
socket.close();
|
||||||
|
location.reload(true); // force reload from server (not from cache)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.onbeforeunload = function() {
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="ace.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script src="editor.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script src="mode-rust.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
<script src="book.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
|
||||||
|
<!-- Custom JS scripts -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -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><a href="0_0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html" class="active"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html" class="active"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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,7 +152,7 @@
|
|||||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||||
<!-- Mobile navigation buttons -->
|
<!-- Mobile navigation buttons -->
|
||||||
|
|
||||||
<a rel="prev" href="2_0_future_example.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a rel="prev" href="7_conclusion.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@
|
|||||||
|
|
||||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||||
|
|
||||||
<a href="2_0_future_example.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
<a href="7_conclusion.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||||
<i class="fa fa-angle-left"></i>
|
<i class="fa fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@@ -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><a href="0_0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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>
|
||||||
|
|||||||
115
book/print.html
115
book/print.html
@@ -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><a href="0_0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_0_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="1_4_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">8.</strong> Bonus 1: concurrent futures</a></li></ol>
|
<ol class="chapter"><li><a href="0_introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li><a href="1_background_information.html"><strong aria-hidden="true">2.</strong> Some background information</a></li><li><a href="2_trait_objects.html"><strong aria-hidden="true">3.</strong> Trait objects and fat pointers</a></li><li><a href="3_generators_pin.html"><strong aria-hidden="true">4.</strong> Generators and Pin</a></li><li><a href="4_pin.html"><strong aria-hidden="true">5.</strong> Pin</a></li><li><a href="5_reactor_executor.html"><strong aria-hidden="true">6.</strong> Reactor/Executor Pattern</a></li><li><a href="6_future_example.html"><strong aria-hidden="true">7.</strong> The main example</a></li><li><a href="7_conclusion.html"><strong aria-hidden="true">8.</strong> Conclusion and exercises</a></li><li><a href="8_concurrent_futures.html"><strong aria-hidden="true">9.</strong> Bonus 1: concurrent futures</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>
|
||||||
@@ -534,7 +534,7 @@ impl Generator for GeneratorA {
|
|||||||
match std::mem::replace(&mut *self, GeneratorA::Exit) {
|
match std::mem::replace(&mut *self, GeneratorA::Exit) {
|
||||||
GeneratorA::Enter(a1) => {
|
GeneratorA::Enter(a1) => {
|
||||||
|
|
||||||
/*|---code before yield1---|*/
|
/*|---code before yield---|*/
|
||||||
/*|*/ println!("Hello"); /*|*/
|
/*|*/ println!("Hello"); /*|*/
|
||||||
/*|*/ let a = a1 * 2; /*|*/
|
/*|*/ let a = a1 * 2; /*|*/
|
||||||
/*|------------------------|*/
|
/*|------------------------|*/
|
||||||
@@ -544,7 +544,7 @@ impl Generator for GeneratorA {
|
|||||||
}
|
}
|
||||||
GeneratorA::Yield1(_) => {
|
GeneratorA::Yield1(_) => {
|
||||||
|
|
||||||
/*|----code after yield1----|*/
|
/*|----code after yield----|*/
|
||||||
/*|*/ println!("world!"); /*|*/
|
/*|*/ println!("world!"); /*|*/
|
||||||
/*|-------------------------|*/
|
/*|-------------------------|*/
|
||||||
|
|
||||||
@@ -555,6 +555,7 @@ impl Generator for GeneratorA {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p>The <code>yield</code> keyword was discussed first in <a href="https://github.com/rust-lang/rfcs/pull/1823">RFC#1823</a> and in <a href="https://github.com/rust-lang/rfcs/pull/1832">RFC#1832</a>.</p>
|
<p>The <code>yield</code> keyword was discussed first in <a href="https://github.com/rust-lang/rfcs/pull/1823">RFC#1823</a> and in <a href="https://github.com/rust-lang/rfcs/pull/1832">RFC#1832</a>.</p>
|
||||||
@@ -652,6 +653,7 @@ into itself.</p>
|
|||||||
if let GeneratorState::Yielded(n) = gen.resume() {
|
if let GeneratorState::Yielded(n) = gen.resume() {
|
||||||
println!("Got value {}", n);
|
println!("Got value {}", n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If you uncomment this, very bad things can happen. This is why we need `Pin`
|
// If you uncomment this, very bad things can happen. This is why we need `Pin`
|
||||||
// std::mem::swap(&mut gen, &mut gen2);
|
// std::mem::swap(&mut gen, &mut gen2);
|
||||||
|
|
||||||
@@ -984,36 +986,13 @@ with the data stored at the memory location <code>test2</code> is pointing to an
|
|||||||
occupied with the string "test2". This can be a bit hard to visualize so I made
|
occupied with the string "test2". This can be a bit hard to visualize so I made
|
||||||
a figure that i hope can help.</p>
|
a figure that i hope can help.</p>
|
||||||
<p><strong>Fig 1: Before and after swap</strong>
|
<p><strong>Fig 1: Before and after swap</strong>
|
||||||
<img src="../assets/swap_problem.jpg" alt="swap_problem" /></p>
|
<img src="./assets/swap_problem.jpg" alt="swap_problem" /></p>
|
||||||
<p>As you can see this results in unwanted behavior. It's easy to get this to
|
<p>As you can see this results in unwanted behavior. It's easy to get this to
|
||||||
segfault, show UB and fail in other spectacular ways as well.</p>
|
segfault, show UB and fail in other spectacular ways as well.</p>
|
||||||
<p>If we change the example to using <code>Pin</code> instead:</p>
|
<p>If we change the example to using <code>Pin</code> instead:</p>
|
||||||
<pre><pre class="playpen"><code class="language-rust editable">use std::pin::Pin;
|
<pre><pre class="playpen"><code class="language-rust editable">use std::pin::Pin;
|
||||||
use std::marker::PhantomPinned;
|
use std::marker::PhantomPinned;
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
let mut test1 = Test::new("test1");
|
|
||||||
test1.init();
|
|
||||||
let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) };
|
|
||||||
let mut test2 = Test::new("test2");
|
|
||||||
test2.init();
|
|
||||||
let mut test2_pin = unsafe { Pin::new_unchecked(&mut test2) };
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"a: {}, b: {}",
|
|
||||||
Test::a(test1_pin.as_ref()),
|
|
||||||
Test::b(test1_pin.as_ref())
|
|
||||||
);
|
|
||||||
|
|
||||||
// Try to uncomment this and see what happens
|
|
||||||
// std::mem::swap(test1_pin.as_mut(), test2_pin.as_mut());
|
|
||||||
println!(
|
|
||||||
"a: {}, b: {}",
|
|
||||||
Test::a(test2_pin.as_ref()),
|
|
||||||
Test::b(test2_pin.as_ref())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Test {
|
struct Test {
|
||||||
a: String,
|
a: String,
|
||||||
@@ -1046,6 +1025,29 @@ impl Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut test1 = Test::new("test1");
|
||||||
|
test1.init();
|
||||||
|
let mut test1_pin = unsafe { Pin::new_unchecked(&mut test1) };
|
||||||
|
let mut test2 = Test::new("test2");
|
||||||
|
test2.init();
|
||||||
|
let mut test2_pin = unsafe { Pin::new_unchecked(&mut test2) };
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"a: {}, b: {}",
|
||||||
|
Test::a(test1_pin.as_ref()),
|
||||||
|
Test::b(test1_pin.as_ref())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try to uncomment this and see what happens
|
||||||
|
// std::mem::swap(test1_pin.as_mut(), test2_pin.as_mut());
|
||||||
|
println!(
|
||||||
|
"a: {}, b: {}",
|
||||||
|
Test::a(test2_pin.as_ref()),
|
||||||
|
Test::b(test2_pin.as_ref())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
<p>Now, what we've done here is pinning a stack address. That will always be
|
<p>Now, what we've done here is pinning a stack address. That will always be
|
||||||
<code>unsafe</code> if our type implements <code>!Unpin</code> (aka <code>MustStay</code>). </p>
|
<code>unsafe</code> if our type implements <code>!Unpin</code> (aka <code>MustStay</code>). </p>
|
||||||
@@ -1060,17 +1062,6 @@ any pointers we take to "self" is invalidated.</p>
|
|||||||
<pre><pre class="playpen"><code class="language-rust editbable">use std::pin::Pin;
|
<pre><pre class="playpen"><code class="language-rust editbable">use std::pin::Pin;
|
||||||
use std::marker::PhantomPinned;
|
use std::marker::PhantomPinned;
|
||||||
|
|
||||||
pub fn main() {
|
|
||||||
let mut test1 = Test::new("test1");
|
|
||||||
let mut test2 = Test::new("test2");
|
|
||||||
|
|
||||||
println!("a: {}, b: {}",test1.as_ref().a(), test1.as_ref().b());
|
|
||||||
|
|
||||||
// Try to uncomment this and see what happens
|
|
||||||
// std::mem::swap(&mut test1, &mut test2);
|
|
||||||
println!("a: {}, b: {}",test2.as_ref().a(), test2.as_ref().b());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Test {
|
struct Test {
|
||||||
a: String,
|
a: String,
|
||||||
@@ -1101,6 +1092,17 @@ impl Test {
|
|||||||
unsafe { &*(self.b) }
|
unsafe { &*(self.b) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut test1 = Test::new("test1");
|
||||||
|
let mut test2 = Test::new("test2");
|
||||||
|
|
||||||
|
println!("a: {}, b: {}",test1.as_ref().a(), test1.as_ref().b());
|
||||||
|
|
||||||
|
// Try to uncomment this and see what happens
|
||||||
|
// std::mem::swap(&mut test1, &mut test2);
|
||||||
|
println!("a: {}, b: {}",test2.as_ref().a(), test2.as_ref().b());
|
||||||
|
}
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
<p>The fact that boxing (heap allocating) a value that implements <code>!Unpin</code> is safe
|
<p>The fact that boxing (heap allocating) a value that implements <code>!Unpin</code> is safe
|
||||||
makes sense. Once the data is allocated on the heap it will have a stable address.</p>
|
makes sense. Once the data is allocated on the heap it will have a stable address.</p>
|
||||||
@@ -1704,6 +1706,43 @@ impl Drop for Reactor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</code></pre></pre>
|
</code></pre></pre>
|
||||||
|
<h1><a class="header" href="#conclusion-and-exercises" id="conclusion-and-exercises">Conclusion and exercises</a></h1>
|
||||||
|
<h1><a class="header" href="#reader-excercises" id="reader-excercises">Reader excercises</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 som relatively simple and good exercises:</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 of telling the OS to suspend our thread and wake it up again on our command. Some hints:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Check out <code>CondVars</code>, here are two sources Wikipedia and the docs for <code>CondVar</code></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>
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<ul>
|
||||||
|
<li>Do you want to pass around a reference to this information using an <code>Arc</code>?</li>
|
||||||
|
<li>Do you want to make this information global so it can be accessed from anywhere?</li>
|
||||||
|
</ul>
|
||||||
|
<p>Next , using a <code>Mutex</code> as a synchronization mechanism might be overkill since many methods only reads data. </p>
|
||||||
|
<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="#further-reading" id="further-reading">Further reading</a></h2>
|
||||||
|
<p>There are many great resources for further study. Here are some of my suggestions:</p>
|
||||||
|
<p>The Asyc book:</p>
|
||||||
<h1><a class="header" href="#bonus-1-concurrent-futures" id="bonus-1-concurrent-futures">Bonus 1: concurrent futures</a></h1>
|
<h1><a class="header" href="#bonus-1-concurrent-futures" id="bonus-1-concurrent-futures">Bonus 1: concurrent futures</a></h1>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
47
src/7_conclusion.md
Normal file
47
src/7_conclusion.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Conclusion and exercises
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Reader excercises
|
||||||
|
|
||||||
|
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 som relatively simple and good exercises:
|
||||||
|
|
||||||
|
## 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 of telling the OS to suspend our thread and wake it up again on our command. Some hints:
|
||||||
|
|
||||||
|
* Check out `CondVars`, here are two sources Wikipedia and the docs for `CondVar`
|
||||||
|
* 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
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
* Do you want to pass around a reference to this information using an `Arc`?
|
||||||
|
* Do you want to make this information global so it can be accessed from anywhere?
|
||||||
|
|
||||||
|
Next , using a `Mutex` as a synchronization mechanism might be overkill since many methods only reads data.
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
## Further reading
|
||||||
|
|
||||||
|
There are many great resources for further study. Here are some of my suggestions:
|
||||||
|
|
||||||
|
The Asyc book:
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
# Summary
|
# Summary
|
||||||
|
|
||||||
- [Introduction](./0_0_introduction.md)
|
- [Introduction](./0_introduction.md)
|
||||||
- [Some background information](./1_0_background_information.md)
|
- [Some background information](./1_background_information.md)
|
||||||
- [Trait objects and fat pointers](./1_1_trait_objects.md)
|
- [Trait objects and fat pointers](./2_trait_objects.md)
|
||||||
- [Generators and Pin](./1_2_generators_pin.md)
|
- [Generators and Pin](./3_generators_pin.md)
|
||||||
- [Pin](./1_3_pin.md)
|
- [Pin](./4_pin.md)
|
||||||
- [Reactor/Executor Pattern](./1_4_reactor_executor.md)
|
- [Reactor/Executor Pattern](./5_reactor_executor.md)
|
||||||
- [The main example](./2_0_future_example.md)
|
- [The main example](./6_future_example.md)
|
||||||
- [Bonus 1: concurrent futures](2_1_concurrent_futures.md)
|
- [Conclusion and exercises](7_conclusion.md)
|
||||||
|
- [Bonus 1: concurrent futures](8_concurrent_futures.md)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user