mentat/scopeguard/index.html
2018-08-22 17:04:13 +00:00

316 lines
No EOL
20 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="rustdoc">
<meta name="description" content="API documentation for the Rust `scopeguard` crate.">
<meta name="keywords" content="rust, rustlang, rust-lang, scopeguard">
<title>scopeguard - Rust</title>
<link rel="stylesheet" type="text/css" href="../normalize.css">
<link rel="stylesheet" type="text/css" href="../rustdoc.css" id="mainThemeStyle">
<link rel="stylesheet" type="text/css" href="../dark.css">
<link rel="stylesheet" type="text/css" href="../main.css" id="themeStyle">
<script src="../storage.js"></script>
</head>
<body class="rustdoc mod">
<!--[if lte IE 8]>
<div class="warning">
This old browser is unsupported and will most likely display funky
things.
</div>
<![endif]-->
<nav class="sidebar">
<div class="sidebar-menu">&#9776;</div>
<p class='location'>Crate scopeguard</p><div class="sidebar-elems"><div class="block items"><ul><li><a href="#macros">Macros</a></li><li><a href="#structs">Structs</a></li><li><a href="#enums">Enums</a></li><li><a href="#traits">Traits</a></li><li><a href="#functions">Functions</a></li></ul></div><p class='location'></p><script>window.sidebarCurrent = {name: 'scopeguard', ty: 'mod', relpath: '../'};</script></div>
</nav>
<div class="theme-picker">
<button id="theme-picker" aria-label="Pick another theme!">
<img src="../brush.svg" width="18" alt="Pick another theme!">
</button>
<div id="theme-choices"></div>
</div>
<script src="../theme.js"></script>
<nav class="sub">
<form class="search-form js-only">
<div class="search-container">
<input class="search-input" name="search"
autocomplete="off"
placeholder="Click or press S to search, ? for more options…"
type="search">
</div>
</form>
</nav>
<section id='main' class="content">
<h1 class='fqn'><span class='in-band'>Crate <a class="mod" href=''>scopeguard</a></span><span class='out-of-band'><span id='render-detail'>
<a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">
[<span class='inner'>&#x2212;</span>]
</a>
</span><a class='srclink' href='../src/scopeguard/lib.rs.html#1-409' title='goto source code'>[src]</a></span></h1>
<div class='docblock'><p>A scope guard will run a given closure when it goes out of scope,
even if the code between panics.
(as long as panic doesn't abort)</p>
<h1 id="examples" class="section-header"><a href="#examples">Examples</a></h1><h2 id="defer" class="section-header"><a href="#defer"><code>defer!</code></a></h2>
<p>Use the <code>defer</code> macro to run an operation at scope exit,
either regular scope exit or during unwinding from a panic.</p>
<pre class="rust rust-example-rendered">
<span class="attribute">#[<span class="ident">macro_use</span>(<span class="ident">defer</span>)]</span> <span class="kw">extern</span> <span class="kw">crate</span> <span class="ident">scopeguard</span>;
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">cell</span>::<span class="ident">Cell</span>;
<span class="kw">fn</span> <span class="ident">main</span>() {
<span class="comment">// use a cell to observe drops during and after the scope guard is active</span>
<span class="kw">let</span> <span class="ident">drop_counter</span> <span class="op">=</span> <span class="ident">Cell</span>::<span class="ident">new</span>(<span class="number">0</span>);
{
<span class="comment">// Create a scope guard using `defer!` for the current scope</span>
<span class="macro">defer</span><span class="macro">!</span> {{
<span class="ident">drop_counter</span>.<span class="ident">set</span>(<span class="number">1</span> <span class="op">+</span> <span class="ident">drop_counter</span>.<span class="ident">get</span>());
}};
<span class="comment">// Do regular operations here in the meantime.</span>
<span class="comment">// Just before scope exit: it hasn&#39;t run yet.</span>
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">drop_counter</span>.<span class="ident">get</span>(), <span class="number">0</span>);
<span class="comment">// The following scope end is where the defer closure is called</span>
}
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">drop_counter</span>.<span class="ident">get</span>(), <span class="number">1</span>);
}</pre>
<h2 id="scope-guard-with-value" class="section-header"><a href="#scope-guard-with-value">Scope Guard with Value</a></h2>
<p>If the scope guard closure needs to access an outer value that is also
mutated outside of the scope guard, then you may want to use the scope guard
with a value. The guard works like a smart pointer, so the inner value can
be accessed by reference or by mutable reference.</p>
<h3 id="1-the-guard-owns-a-file" class="section-header"><a href="#1-the-guard-owns-a-file">1. The guard owns a file</a></h3>
<p>In this example, the scope guard owns a file and ensures pending writes are
synced at scope exit.</p>
<pre class="rust rust-example-rendered">
<span class="kw">extern</span> <span class="kw">crate</span> <span class="ident">scopeguard</span>;
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">fs</span>::<span class="ident">File</span>;
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">io</span>::{<span class="self">self</span>, <span class="ident">Write</span>};
<span class="kw">fn</span> <span class="ident">try_main</span>() <span class="op">-&gt;</span> <span class="ident">io</span>::<span class="prelude-ty">Result</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">f</span> <span class="op">=</span> <span class="ident">File</span>::<span class="ident">create</span>(<span class="string">&quot;newfile.txt&quot;</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">file</span> <span class="op">=</span> <span class="ident">scopeguard</span>::<span class="ident">guard</span>(<span class="ident">f</span>, <span class="op">|</span><span class="ident">f</span><span class="op">|</span> {
<span class="comment">// ensure we flush file at return or panic</span>
<span class="kw">let</span> _ <span class="op">=</span> <span class="ident">f</span>.<span class="ident">sync_all</span>();
});
<span class="comment">// Access the file through the scope guard itself</span>
<span class="ident">file</span>.<span class="ident">write</span>(<span class="string">b&quot;test me\n&quot;</span>).<span class="ident">map</span>(<span class="op">|</span>_<span class="op">|</span> ())
}
<span class="kw">fn</span> <span class="ident">main</span>() {
<span class="ident">try_main</span>().<span class="ident">unwrap</span>();
}
</pre>
<h3 id="2-the-guard-restores-an-invariant-on-scope-exit" class="section-header"><a href="#2-the-guard-restores-an-invariant-on-scope-exit">2. The guard restores an invariant on scope exit</a></h3>
<pre class="rust rust-example-rendered">
<span class="kw">extern</span> <span class="kw">crate</span> <span class="ident">scopeguard</span>;
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">mem</span>::<span class="ident">ManuallyDrop</span>;
<span class="kw">use</span> <span class="ident">std</span>::<span class="ident">ptr</span>;
<span class="comment">// This function, just for this example, takes the first element</span>
<span class="comment">// and inserts it into the assumed sorted tail of the vector.</span>
<span class="comment">//</span>
<span class="comment">// For optimization purposes we temporarily violate an invariant of the</span>
<span class="comment">// Vec, that it owns all of its elements.</span>
<span class="comment">// </span>
<span class="comment">// The safe approach is to use swap, which means two writes to memory,</span>
<span class="comment">// the optimization is to use a “hole” which uses only one write of memory</span>
<span class="comment">// for each position it moves.</span>
<span class="comment">//</span>
<span class="comment">// We *must* use a scope guard to run this code safely. We</span>
<span class="comment">// are running arbitrary user code (comparison operators) that may panic.</span>
<span class="comment">// The scope guard ensures we restore the invariant after successful</span>
<span class="comment">// exit or during unwinding from panic.</span>
<span class="kw">fn</span> <span class="ident">insertion_sort_first</span><span class="op">&lt;</span><span class="ident">T</span><span class="op">&gt;</span>(<span class="ident">v</span>: <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">T</span><span class="op">&gt;</span>)
<span class="kw">where</span> <span class="ident">T</span>: <span class="ident">PartialOrd</span>
{
<span class="kw">struct</span> <span class="ident">Hole</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span>, <span class="ident">T</span>: <span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="ident">v</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="kw-2">mut</span> <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">T</span><span class="op">&gt;</span>,
<span class="ident">index</span>: <span class="ident">usize</span>,
<span class="ident">value</span>: <span class="ident">ManuallyDrop</span><span class="op">&lt;</span><span class="ident">T</span><span class="op">&gt;</span>,
}
<span class="kw">unsafe</span> {
<span class="comment">// Create a moved-from location in the vector, a “hole”.</span>
<span class="kw">let</span> <span class="ident">value</span> <span class="op">=</span> <span class="ident">ptr</span>::<span class="ident">read</span>(<span class="kw-2">&amp;</span><span class="ident">v</span>[<span class="number">0</span>]);
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">hole</span> <span class="op">=</span> <span class="ident">Hole</span> { <span class="ident">v</span>: <span class="ident">v</span>, <span class="ident">index</span>: <span class="number">0</span>, <span class="ident">value</span>: <span class="ident">ManuallyDrop</span>::<span class="ident">new</span>(<span class="ident">value</span>) };
<span class="comment">// Use a scope guard with a value.</span>
<span class="comment">// At scope exit, plug the hole so that the vector is fully</span>
<span class="comment">// initialized again.</span>
<span class="comment">// The scope guard owns the hole, but we can access it through the guard.</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">hole_guard</span> <span class="op">=</span> <span class="ident">scopeguard</span>::<span class="ident">guard</span>(<span class="ident">hole</span>, <span class="op">|</span><span class="ident">hole</span><span class="op">|</span> {
<span class="comment">// plug the hole in the vector with the value that was // taken out</span>
<span class="kw">let</span> <span class="ident">index</span> <span class="op">=</span> <span class="ident">hole</span>.<span class="ident">index</span>;
<span class="ident">ptr</span>::<span class="ident">copy_nonoverlapping</span>(<span class="kw-2">&amp;</span><span class="kw-2">*</span><span class="ident">hole</span>.<span class="ident">value</span>, <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">hole</span>.<span class="ident">v</span>[<span class="ident">index</span>], <span class="number">1</span>);
});
<span class="comment">// run algorithm that moves the hole in the vector here</span>
<span class="comment">// move the hole until it&#39;s in a sorted position</span>
<span class="kw">for</span> <span class="ident">i</span> <span class="kw">in</span> <span class="number">1</span>..<span class="ident">hole_guard</span>.<span class="ident">v</span>.<span class="ident">len</span>() {
<span class="kw">if</span> <span class="kw-2">*</span><span class="ident">hole_guard</span>.<span class="ident">value</span> <span class="op">&gt;=</span> <span class="ident">hole_guard</span>.<span class="ident">v</span>[<span class="ident">i</span>] {
<span class="comment">// move the element back and the hole forward</span>
<span class="kw">let</span> <span class="ident">index</span> <span class="op">=</span> <span class="ident">hole_guard</span>.<span class="ident">index</span>;
<span class="ident">ptr</span>::<span class="ident">copy_nonoverlapping</span>(<span class="kw-2">&amp;</span><span class="ident">hole_guard</span>.<span class="ident">v</span>[<span class="ident">index</span> <span class="op">+</span> <span class="number">1</span>], <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">hole_guard</span>.<span class="ident">v</span>[<span class="ident">index</span>], <span class="number">1</span>);
<span class="ident">hole_guard</span>.<span class="ident">index</span> <span class="op">+=</span> <span class="number">1</span>;
} <span class="kw">else</span> {
<span class="kw">break</span>;
}
}
<span class="comment">// When the scope exits here, the Vec becomes whole again!</span>
}
}
<span class="kw">fn</span> <span class="ident">main</span>() {
<span class="kw">let</span> <span class="ident">string</span> <span class="op">=</span> <span class="ident">String</span>::<span class="ident">from</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">data</span> <span class="op">=</span> <span class="macro">vec</span><span class="macro">!</span>[<span class="ident">string</span>(<span class="string">&quot;c&quot;</span>), <span class="ident">string</span>(<span class="string">&quot;a&quot;</span>), <span class="ident">string</span>(<span class="string">&quot;b&quot;</span>), <span class="ident">string</span>(<span class="string">&quot;d&quot;</span>)];
<span class="ident">insertion_sort_first</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">data</span>);
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">data</span>, <span class="macro">vec</span><span class="macro">!</span>[<span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;d&quot;</span>]);
}
</pre>
<h1 id="crate-features" class="section-header"><a href="#crate-features">Crate features:</a></h1>
<ul>
<li><code>use_std</code>
<ul>
<li>Enabled by default. Enables the <code>OnUnwind</code> strategy.</li>
<li>Disable to use <code>no_std</code>.</li>
</ul>
</li>
</ul>
</div><h2 id='macros' class='section-header'><a href="#macros">Macros</a></h2>
<table>
<tr class=' module-item'>
<td><a class="macro" href="macro.defer.html"
title='macro scopeguard::defer'>defer</a></td>
<td class='docblock-short'>
<p>Macro to create a <code>ScopeGuard</code> (always run).</p>
</td>
</tr>
<tr class=' module-item'>
<td><a class="macro" href="macro.defer_on_unwind.html"
title='macro scopeguard::defer_on_unwind'>defer_on_unwind</a></td>
<td class='docblock-short'>
<p>Macro to create a <code>ScopeGuard</code> (run on unwinding from panic).</p>
</td>
</tr></table><h2 id='structs' class='section-header'><a href="#structs">Structs</a></h2>
<table>
<tr class=' module-item'>
<td><a class="struct" href="struct.ScopeGuard.html"
title='struct scopeguard::ScopeGuard'>ScopeGuard</a></td>
<td class='docblock-short'>
<p><code>ScopeGuard</code> is a scope guard that may own a protected value.</p>
</td>
</tr></table><h2 id='enums' class='section-header'><a href="#enums">Enums</a></h2>
<table>
<tr class=' module-item'>
<td><a class="enum" href="enum.Always.html"
title='enum scopeguard::Always'>Always</a></td>
<td class='docblock-short'>
<p>Always run on scope exit.</p>
</td>
</tr></table><h2 id='traits' class='section-header'><a href="#traits">Traits</a></h2>
<table>
<tr class=' module-item'>
<td><a class="trait" href="trait.Strategy.html"
title='trait scopeguard::Strategy'>Strategy</a></td>
<td class='docblock-short'>
</td>
</tr></table><h2 id='functions' class='section-header'><a href="#functions">Functions</a></h2>
<table>
<tr class=' module-item'>
<td><a class="fn" href="fn.guard.html"
title='fn scopeguard::guard'>guard</a></td>
<td class='docblock-short'>
<p>Create a new <code>ScopeGuard</code> owning <code>v</code> and with deferred closure <code>dropfn</code>.</p>
</td>
</tr></table></section>
<section id='search' class="content hidden"></section>
<section class="footer"></section>
<aside id="help" class="hidden">
<div>
<h1 class="hidden">Help</h1>
<div class="shortcuts">
<h2>Keyboard Shortcuts</h2>
<dl>
<dt><kbd>?</kbd></dt>
<dd>Show this help dialog</dd>
<dt><kbd>S</kbd></dt>
<dd>Focus the search field</dd>
<dt><kbd></kbd></dt>
<dd>Move up in search results</dd>
<dt><kbd></kbd></dt>
<dd>Move down in search results</dd>
<dt><kbd></kbd></dt>
<dd>Switch tab</dd>
<dt><kbd>&#9166;</kbd></dt>
<dd>Go to active search result</dd>
<dt><kbd>+</kbd></dt>
<dd>Expand all sections</dd>
<dt><kbd>-</kbd></dt>
<dd>Collapse all sections</dd>
</dl>
</div>
<div class="infos">
<h2>Search Tricks</h2>
<p>
Prefix searches with a type followed by a colon (e.g.
<code>fn:</code>) to restrict the search to a given type.
</p>
<p>
Accepted types are: <code>fn</code>, <code>mod</code>,
<code>struct</code>, <code>enum</code>,
<code>trait</code>, <code>type</code>, <code>macro</code>,
and <code>const</code>.
</p>
<p>
Search functions by type signature (e.g.
<code>vec -> usize</code> or <code>* -> vec</code>)
</p>
</div>
</div>
</aside>
<script>
window.rootPath = "../";
window.currentCrate = "scopeguard";
</script>
<script src="../main.js"></script>
<script defer src="../search-index.js"></script>
</body>
</html>