finished all but the main example

This commit is contained in:
Carl Fredrik Samson
2020-02-01 00:01:15 +01:00
parent a84ec7d6c8
commit 013fd3bb48
20 changed files with 1704 additions and 581 deletions

View File

@@ -78,7 +78,7 @@
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<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><ol class="section"><li><a href="1_1_trait_objects.html"><strong aria-hidden="true">2.1.</strong> Trait objects and fat pointers</a></li><li><a href="1_2_generators_pin.html"><strong aria-hidden="true">2.2.</strong> Generators and Pin</a></li><li><a href="1_3_pin.html" class="active"><strong aria-hidden="true">2.3.</strong> Pin</a></li></ol></li><li><a href="2_0_future_example.html"><strong aria-hidden="true">3.</strong> The main example</a></li><li><a href="2_1_concurrent_futures.html"><strong aria-hidden="true">4.</strong> Bonus 1: concurrent futures</a></li></ol>
<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>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
@@ -145,7 +145,7 @@
<div id="content" class="content">
<main>
<h2><a class="header" href="#pin" id="pin">Pin</a></h2>
<h1><a class="header" href="#pin" id="pin">Pin</a></h1>
<blockquote>
<p><strong>Relevant for</strong></p>
<ol>
@@ -156,23 +156,60 @@
</ol>
<p><code>Pin</code> was suggested in <a href="https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md">RFC#2349</a></p>
</blockquote>
<p>Ping consists of the <code>Pin</code> type and the <code>Unpin</code> marker. Let's start off with some general rules:</p>
<p>We already got a brief introduction of <code>Pin</code> in the previous chapters, so we'll
start off here with some definitions and a set of rules to remember.</p>
<h2><a class="header" href="#definitions" id="definitions">Definitions</a></h2>
<p>Pin consists of the <code>Pin</code> type and the <code>Unpin</code> marker. Pin's purpose in life is
to govern the rules that need to apply for types which implement <code>!Unpin</code>.</p>
<p>Pin is only relevant for pointers. A reference to an object is a pointer.</p>
<p>Yep, that's double negation for you, as in &quot;does-not-implement-unpin&quot;. For this
chapter and only this chapter we'll rename these markers to:</p>
<blockquote>
<p><code>!Unpin</code> = <code>MustStay</code> and <code>Unpin</code> = <code>CanMove</code></p>
</blockquote>
<p>It just makes it so much easier to understand them.</p>
<h2><a class="header" href="#rules-to-remember" id="rules-to-remember">Rules to remember</a></h2>
<ol>
<li>Pin does nothing special, it only prevents the user of an API to violate some assumtions you make when writing your (most likely) unsafe code.</li>
<li>Most standard library types implement <code>Unpin</code></li>
<li><code>Unpin</code> means it's OK for this type to be moved even when pinned.</li>
<li>If you <code>Box</code> a value, that boxed value automatcally implements <code>Unpin</code>.</li>
<li>The main use case for <code>Pin</code> is to allow self referential types</li>
<li>The implementation behind objects that doens't implement <code>Unpin</code> is most likely unsafe
<ol>
<li><code>Pin</code> prevents users from your code to break the assumtions you make when writing the <code>unsafe</code> implementation</li>
<li>It doesn't solve the fact that you'll have to write unsafe code to actually implement it</li>
</ol>
<li>
<p>If <code>T: CanMove</code> (which is the default), then <code>Pin&lt;'a, T&gt;</code> is entirely equivalent to <code>&amp;'a mut T</code>. in other words: <code>CanMove</code> means it's OK for this type to be moved even when pinned, so <code>Pin</code> will have no effect on such a type.</p>
</li>
<li>
<p>Getting a <code>&amp;mut T</code> to a pinned pointer requires unsafe if <code>T: MustStay</code>. In other words: requiring a pinned pointer to a type which is <code>MustStay</code> prevents the <em>user</em> of that API from moving that value unless it choses to write <code>unsafe</code> code.</p>
</li>
<li>
<p>Pinning does nothing special with that memory like putting it into some &quot;read only&quot; memory or anything fancy. It only tells the compiler that some operations on this value should be forbidden. </p>
</li>
<li>
<p>Most standard library types implement <code>CanMove</code>. The same goes for most
&quot;normal&quot; types you encounter in Rust. <code>Futures</code> and <code>Generators</code> are two
exceptions.</p>
</li>
<li>
<p>The main use case for <code>Pin</code> is to allow self referential types, the whole
justification for stabilizing them was to allow that. There are still corner
cases in the API which are being explored.</p>
</li>
<li>
<p>The implementation behind objects that are <code>MustStay</code> is most likely unsafe.
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>
</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>
</li>
<li>
<p>When Pinning, you can either pin a value to memory either on the stack or
on the heap.</p>
</li>
<li>
<p>Pinning a <code>MustStay</code> pointer to the stack requires <code>unsafe</code></p>
</li>
<li>
<p>Pinning a <code>MustStay</code> pointer to the heap does not require <code>unsafe</code>. There is a shortcut for doing this using <code>Box::pin</code>.</p>
</li>
<li>You're not really meant to be implementing <code>!Unpin</code>, but you can on nightly with a feature flag</li>
</ol>
<blockquote>
<p>Unsafe code does not mean it's litterally &quot;unsafe&quot;, it only relieves the
<p>Unsafe code does not mean it's literally &quot;unsafe&quot;, it only relieves the
guarantees you normally get from the compiler. An <code>unsafe</code> implementation can
be perfectly safe to do, but you have no safety net.</p>
</blockquote>
@@ -220,11 +257,30 @@ impl Test {
}
}
</code></pre></pre>
<p>As you can see this results in unwanted behavior. The pointer to <code>b</code> stays the
same and points to the old value. It's easy to get this to segfault, and fail
in other spectacular ways as well.</p>
<p>Pin essentially prevents the <strong>user</strong> of your unsafe code
(even if that means yourself) move the value after it's pinned.</p>
<p>Let's walk through this example since we'll be using it the rest of this chapter.</p>
<p>We have a self-referential struct <code>Test</code>. <code>Test</code> needs an <code>init</code> method to be
created which is strange but we'll need that to keep this example as short as
possible.</p>
<p><code>Test</code> provides two methods to get a reference to the value of the fields
<code>a</code> and <code>b</code>. Since <code>b</code> is a reference to <code>a</code> we store it as a pointer since
the borrowing rules of Rust doesn't allow us to define this lifetime.</p>
<p>In our main method we first instantiate two instances of <code>Test</code> and print out
the value of the fields on <code>test1</code>. We get:</p>
<pre><code class="language-rust ignore">a: test1, b: test1
</code></pre>
<p>Next we swap the data stored at the memory location which <code>test1</code> is pointing to
with the data stored at the memory location <code>test2</code> is pointing to and vice a verca.</p>
<p>We should expect that printing the fields of <code>test2</code> should display the same as
<code>test1</code> (since the object we printed before the swap has moved there now).</p>
<pre><code class="language-rust ignore">a: test1, b: test2
</code></pre>
<p>The pointer to <code>b</code> still points to the old location. That location is now
occupied with the string &quot;test2&quot;. This can be a bit hard to visualize so I made
a figure that i hope can help.</p>
<p><strong>Fig 1: Before and after swap</strong>
<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
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>
<pre><pre class="playpen"><code class="language-rust editable">use std::pin::Pin;
use std::marker::PhantomPinned;
@@ -286,13 +342,14 @@ impl Test {
</code></pre></pre>
<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>, in other words. That our type is not
<code>Unpin</code> which is the norm.</p>
<code>unsafe</code> if our type implements <code>!Unpin</code> (aka <code>MustStay</code>). </p>
<p>We use some tricks here, including requiring an <code>init</code>. If we want to fix that
and let users avoid <code>unsafe</code> we need to place our data on the heap.</p>
and let users avoid <code>unsafe</code> we need to pin our data on the heap instead.</p>
<blockquote>
<p>Stack pinning will always depend on the current stack frame we're in, so we
can't create a self referential object in one stack frame and return it since
any pointers we take to &quot;self&quot; is invalidated.</p>
</blockquote>
<p>The next example solves some of our friction at the cost of a heap allocation.</p>
<pre><pre class="playpen"><code class="language-rust editbable">use std::pin::Pin;
use std::marker::PhantomPinned;
@@ -339,19 +396,10 @@ impl Test {
}
}
</code></pre></pre>
<p>Seeing this we're ready to sum up with a few more points to remember about
pinning:</p>
<ol>
<li>Pinning only makes sense to do for types that are <code>!Unpin</code></li>
<li>Pinning a <code>!Unpin</code> pointer to the stack will requires <code>unsafe</code></li>
<li>Pinning a boxed value will not require <code>unsafe</code>, even if the type is <code>!Unpin</code></li>
<li>If T: Unpin (which is the default), then Pin&lt;'a, T&gt; is entirely equivalent to &amp;'a mut T.</li>
<li>Getting a <code>&amp;mut T</code> to a pinned pointer requires unsafe if <code>T: !Unpin</code></li>
<li>Pinning is really only useful when implementing self-referential types.<br />
For all intents and purposes you can think of <code>!Unpin</code> = self-referential-type</li>
</ol>
<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>
<p>There is no need for us as users of the API to take special care and ensure
that the self-referential pointer stays valid.</p>
<p>There are ways to safely give some guarantees on stack pinning as well, but right
now you need to use a crate like <a href="https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md">pin_utils</a>:<a href="https://github.com/rust-lang/rfcs/blob/master/text/2349-pin.md">pin_utils</a> to do that.</p>
<h3><a class="header" href="#projectionstructural-pinning" id="projectionstructural-pinning">Projection/structural pinning</a></h3>
@@ -378,7 +426,7 @@ we're soon finished.</p>
<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="1_4_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>
</a>
@@ -396,7 +444,7 @@ we're soon finished.</p>
<a href="2_0_future_example.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<a href="1_4_reactor_executor.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>