added playground links to show problem using thread park/unpark

This commit is contained in:
Carl Fredrik Samson
2020-04-14 00:33:34 +02:00
parent 08b155698c
commit 2fc79a9e03
7 changed files with 38 additions and 20 deletions

View File

@@ -274,7 +274,7 @@ fn main() {
// length of the array is encoded in the array itself as the second value. // length of the array is encoded in the array itself as the second value.
let vtable = vec![ let vtable = vec![
0, // pointer to `Drop` (which we're not implementing here) 0, // pointer to `Drop` (which we're not implementing here)
6, // lenght of vtable 6, // length of vtable
8, // alignment 8, // alignment
// we need to make sure we add these in the same order as defined in the Trait. // we need to make sure we add these in the same order as defined in the Trait.

View File

@@ -434,7 +434,7 @@ we'll show in a second.</p>
<pre><pre class="playpen"><code class="language-rust">pub fn main() { <pre><pre class="playpen"><code class="language-rust">pub fn main() {
// test1 is safe to move before we initialize it // test1 is safe to move before we initialize it
let mut test1 = Test::new(&quot;test1&quot;); let mut test1 = Test::new(&quot;test1&quot;);
// Notice how we shadow `test1` to prevent it from beeing accessed again // Notice how we shadow `test1` to prevent it from being accessed again
let mut test1 = unsafe { Pin::new_unchecked(&amp;mut test1) }; let mut test1 = unsafe { Pin::new_unchecked(&amp;mut test1) };
Test::init(test1.as_mut()); Test::init(test1.as_mut());

View File

@@ -305,7 +305,7 @@ const VTABLE: RawWakerVTable = unsafe {
) )
}; };
// Instead of implementing this on the `MyWaker` oject in `impl Mywaker...` we // Instead of implementing this on the `MyWaker` object in `impl Mywaker...` we
// just use this pattern instead since it saves us some lines of code. // just use this pattern instead since it saves us some lines of code.
fn waker_into_waker(s: *const MyWaker) -&gt; Waker { fn waker_into_waker(s: *const MyWaker) -&gt; Waker {
let raw_waker = RawWaker::new(s as *const (), &amp;VTABLE); let raw_waker = RawWaker::new(s as *const (), &amp;VTABLE);
@@ -389,9 +389,9 @@ without passing around a reference.</p>
<blockquote> <blockquote>
<h3><a class="header" href="#why-using-thread-parkunpark-is-a-bad-idea-for-a-library" id="why-using-thread-parkunpark-is-a-bad-idea-for-a-library">Why using thread park/unpark is a bad idea for a library</a></h3> <h3><a class="header" href="#why-using-thread-parkunpark-is-a-bad-idea-for-a-library" id="why-using-thread-parkunpark-is-a-bad-idea-for-a-library">Why using thread park/unpark is a bad idea for a library</a></h3>
<p>It could deadlock easily since anyone could get a handle to the <code>executor thread</code> <p>It could deadlock easily since anyone could get a handle to the <code>executor thread</code>
and call park/unpark on our thread or we could have a race condition where the and call park/unpark on our thread. I've made <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=b2343661fe3d271c91c6977ab8e681d0">an example with comments on the
future resolves and calls <code>wake</code> before we have time to go to sleep in our playground</a> that showcases how such an error could occur. You can also read a bit more about this in <a href="https://github.com/rust-lang/futures-rs/pull/2010">issue 2010</a>
executor. We'll se how we can fix this at the end of this chapter.</p> in the futures crate.</p>
</blockquote> </blockquote>
<h2><a class="header" href="#the-reactor" id="the-reactor">The Reactor</a></h2> <h2><a class="header" href="#the-reactor" id="the-reactor">The Reactor</a></h2>
<p>This is the home stretch, and not strictly <code>Future</code> related, but we need one <p>This is the home stretch, and not strictly <code>Future</code> related, but we need one
@@ -898,7 +898,13 @@ fn mywaker_wake(s: &amp;MyWaker) {
waker_arc.parker.unpark(); waker_arc.parker.unpark();
} }
</code></pre> </code></pre>
<p>And that's really all there is to it. The next chapter shows our finished code with this <p>And that's really all there is to it. </p>
<blockquote>
<p>If you checked out the playground link that showcased how park/unpark could <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=b2343661fe3d271c91c6977ab8e681d0">cause subtle
problems</a>
you can <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=bebef0f8a8ce6a9d0d32442cc8381595">check out this example</a> which shows how our final version avoids this problem.</p>
</blockquote>
<p>The next chapter shows our finished code with this
improvement which you can explore further if you wish.</p> improvement which you can explore further if you wish.</p>
</main> </main>

View File

@@ -1016,7 +1016,7 @@ fn main() {
// length of the array is encoded in the array itself as the second value. // length of the array is encoded in the array itself as the second value.
let vtable = vec![ let vtable = vec![
0, // pointer to `Drop` (which we're not implementing here) 0, // pointer to `Drop` (which we're not implementing here)
6, // lenght of vtable 6, // length of vtable
8, // alignment 8, // alignment
// we need to make sure we add these in the same order as defined in the Trait. // we need to make sure we add these in the same order as defined in the Trait.
@@ -1912,7 +1912,7 @@ we'll show in a second.</p>
<pre><pre class="playpen"><code class="language-rust">pub fn main() { <pre><pre class="playpen"><code class="language-rust">pub fn main() {
// test1 is safe to move before we initialize it // test1 is safe to move before we initialize it
let mut test1 = Test::new(&quot;test1&quot;); let mut test1 = Test::new(&quot;test1&quot;);
// Notice how we shadow `test1` to prevent it from beeing accessed again // Notice how we shadow `test1` to prevent it from being accessed again
let mut test1 = unsafe { Pin::new_unchecked(&amp;mut test1) }; let mut test1 = unsafe { Pin::new_unchecked(&amp;mut test1) };
Test::init(test1.as_mut()); Test::init(test1.as_mut());
@@ -2461,7 +2461,7 @@ const VTABLE: RawWakerVTable = unsafe {
) )
}; };
// Instead of implementing this on the `MyWaker` oject in `impl Mywaker...` we // Instead of implementing this on the `MyWaker` object in `impl Mywaker...` we
// just use this pattern instead since it saves us some lines of code. // just use this pattern instead since it saves us some lines of code.
fn waker_into_waker(s: *const MyWaker) -&gt; Waker { fn waker_into_waker(s: *const MyWaker) -&gt; Waker {
let raw_waker = RawWaker::new(s as *const (), &amp;VTABLE); let raw_waker = RawWaker::new(s as *const (), &amp;VTABLE);
@@ -2545,9 +2545,9 @@ without passing around a reference.</p>
<blockquote> <blockquote>
<h3><a class="header" href="#why-using-thread-parkunpark-is-a-bad-idea-for-a-library" id="why-using-thread-parkunpark-is-a-bad-idea-for-a-library">Why using thread park/unpark is a bad idea for a library</a></h3> <h3><a class="header" href="#why-using-thread-parkunpark-is-a-bad-idea-for-a-library" id="why-using-thread-parkunpark-is-a-bad-idea-for-a-library">Why using thread park/unpark is a bad idea for a library</a></h3>
<p>It could deadlock easily since anyone could get a handle to the <code>executor thread</code> <p>It could deadlock easily since anyone could get a handle to the <code>executor thread</code>
and call park/unpark on our thread or we could have a race condition where the and call park/unpark on our thread. I've made <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=b2343661fe3d271c91c6977ab8e681d0">an example with comments on the
future resolves and calls <code>wake</code> before we have time to go to sleep in our playground</a> that showcases how such an error could occur. You can also read a bit more about this in <a href="https://github.com/rust-lang/futures-rs/pull/2010">issue 2010</a>
executor. We'll se how we can fix this at the end of this chapter.</p> in the futures crate.</p>
</blockquote> </blockquote>
<h2><a class="header" href="#the-reactor" id="the-reactor">The Reactor</a></h2> <h2><a class="header" href="#the-reactor" id="the-reactor">The Reactor</a></h2>
<p>This is the home stretch, and not strictly <code>Future</code> related, but we need one <p>This is the home stretch, and not strictly <code>Future</code> related, but we need one
@@ -3054,7 +3054,13 @@ fn mywaker_wake(s: &amp;MyWaker) {
waker_arc.parker.unpark(); waker_arc.parker.unpark();
} }
</code></pre> </code></pre>
<p>And that's really all there is to it. The next chapter shows our finished code with this <p>And that's really all there is to it. </p>
<blockquote>
<p>If you checked out the playground link that showcased how park/unpark could <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=b2343661fe3d271c91c6977ab8e681d0">cause subtle
problems</a>
you can <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=bebef0f8a8ce6a9d0d32442cc8381595">check out this example</a> which shows how our final version avoids this problem.</p>
</blockquote>
<p>The next chapter shows our finished code with this
improvement which you can explore further if you wish.</p> improvement which you can explore further if you wish.</p>
<h1><a class="header" href="#our-finished-code" id="our-finished-code">Our finished code</a></h1> <h1><a class="header" href="#our-finished-code" id="our-finished-code">Our finished code</a></h1>
<p>Here is the whole example. You can edit it right here in your browser and <p>Here is the whole example. You can edit it right here in your browser and

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -264,9 +264,9 @@ without passing around a reference.
> ### Why using thread park/unpark is a bad idea for a library > ### Why using thread park/unpark is a bad idea for a library
> >
> It could deadlock easily since anyone could get a handle to the `executor thread` > It could deadlock easily since anyone could get a handle to the `executor thread`
> and call park/unpark on our thread or we could have a race condition where the > and call park/unpark on our thread. I've made [an example with comments on the
> future resolves and calls `wake` before we have time to go to sleep in our > playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b2343661fe3d271c91c6977ab8e681d0) that showcases how such an error could occur. You can also read a bit more about this in [issue 2010](https://github.com/rust-lang/futures-rs/pull/2010)
> executor. We'll se how we can fix this at the end of this chapter. > in the futures crate.
## The Reactor ## The Reactor
@@ -821,7 +821,13 @@ fn mywaker_wake(s: &MyWaker) {
} }
``` ```
And that's really all there is to it. The next chapter shows our finished code with this And that's really all there is to it.
> If you checked out the playground link that showcased how park/unpark could [cause subtle
> problems](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b2343661fe3d271c91c6977ab8e681d0)
> you can [check out this example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bebef0f8a8ce6a9d0d32442cc8381595) which shows how our final version avoids this problem.
The next chapter shows our finished code with this
improvement which you can explore further if you wish. improvement which you can explore further if you wish.
[mio]: https://github.com/tokio-rs/mio [mio]: https://github.com/tokio-rs/mio