mirror of
https://github.com/fluencelabs/wasmer
synced 2025-05-18 05:11:18 +00:00
136 lines
15 KiB
HTML
136 lines
15 KiB
HTML
<!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 `generational_arena` crate."><meta name="keywords" content="rust, rustlang, rust-lang, generational_arena"><title>generational_arena - 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="../light.css" id="themeStyle"><script src="../storage.js"></script><noscript><link rel="stylesheet" href="../noscript.css"></noscript><link rel="shortcut icon" href="../favicon.ico"><style type="text/css">#crate-search{background-image:url("../down-arrow.svg");}</style></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">☰</div><a href='../generational_arena/index.html'><div class='logo-container'><img src='../rust-logo.png' alt='logo'></div></a><p class='location'>Crate generational_arena</p><div class="sidebar-elems"><a id='all-types' href='all.html'><p>See all generational_arena's items</p></a><div class="block items"><ul><li><a href="#structs">Structs</a></li></ul></div><p class='location'></p><script>window.sidebarCurrent = {name: 'generational_arena', 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"><div><select id="crate-search"><option value="All crates">All crates</option></select><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press ‘S’ to search, ‘?’ for more options…" type="search"></div><a id="settings-menu" href="../settings.html"><img src="../wheel.svg" width="18" alt="Change settings"></a></div></form></nav><section id="main" class="content"><h1 class='fqn'><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'>−</span>]</a></span><a class='srclink' href='../src/generational_arena/lib.rs.html#1-1161' title='goto source code'>[src]</a></span><span class='in-band'>Crate <a class="mod" href=''>generational_arena</a></span></h1><div class='docblock'><p><a href="https://docs.rs/generational-arena/"><img src="https://docs.rs/generational-arena/badge.svg" alt="" /></a>
|
||
<a href="https://crates.io/crates/generational-arena"><img src="https://img.shields.io/crates/v/generational-arena.svg" alt="" /></a>
|
||
<a href="https://crates.io/crates/generational-arena"><img src="https://img.shields.io/crates/d/generational-arena.svg" alt="" /></a>
|
||
<a href="https://travis-ci.org/fitzgen/generational-arena"><img src="https://travis-ci.org/fitzgen/generational-arena.svg?branch=master" alt="Travis CI Build Status" /></a></p>
|
||
<p>A safe arena allocator that allows deletion without suffering from <a href="https://en.wikipedia.org/wiki/ABA_problem">the ABA
|
||
problem</a> by using generational
|
||
indices.</p>
|
||
<p>Inspired by <a href="http://rustconf.com/program.html#closingkeynote">Catherine West's closing keynote at RustConf
|
||
2018</a>, where these ideas
|
||
were presented in the context of an Entity-Component-System for games
|
||
programming.</p>
|
||
<h2 id="what-why" class="section-header"><a href="#what-why">What? Why?</a></h2>
|
||
<p>Imagine you are working with a graph and you want to add and delete individual
|
||
nodes at a time, or you are writing a game and its world consists of many
|
||
inter-referencing objects with dynamic lifetimes that depend on user
|
||
input. These are situations where matching Rust's ownership and lifetime rules
|
||
can get tricky.</p>
|
||
<p>It doesn't make sense to use shared ownership with interior mutability (ie
|
||
<code>Rc<RefCell<T>></code> or <code>Arc<Mutex<T>></code>) nor borrowed references (ie <code>&'a T</code> or <code>&'a mut T</code>) for structures. The cycles rule out reference counted types, and the
|
||
required shared mutability rules out borrows. Furthermore, lifetimes are dynamic
|
||
and don't follow the borrowed-data-outlives-the-borrower discipline.</p>
|
||
<p>In these situations, it is tempting to store objects in a <code>Vec<T></code> and have them
|
||
reference each other via their indices. No more borrow checker or ownership
|
||
problems! Often, this solution is good enough.</p>
|
||
<p>However, now we can't delete individual items from that <code>Vec<T></code> when we no
|
||
longer need them, because we end up either</p>
|
||
<ul>
|
||
<li>
|
||
<p>messing up the indices of every element that follows the deleted one, or</p>
|
||
</li>
|
||
<li>
|
||
<p>suffering from the <a href="https://en.wikipedia.org/wiki/ABA_problem">ABA
|
||
problem</a>. To elaborate further, if
|
||
we tried to replace the <code>Vec<T></code> with a <code>Vec<Option<T>></code>, and delete an
|
||
element by setting it to <code>None</code>, then we create the possibility for this buggy
|
||
sequence:</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>obj1</code> references <code>obj2</code> at index <code>i</code></p>
|
||
</li>
|
||
<li>
|
||
<p>someone else deletes <code>obj2</code> from index <code>i</code>, setting that element to <code>None</code></p>
|
||
</li>
|
||
<li>
|
||
<p>a third thing allocates <code>obj3</code>, which ends up at index <code>i</code>, because the
|
||
element at that index is <code>None</code> and therefore available for allocation</p>
|
||
</li>
|
||
<li>
|
||
<p><code>obj1</code> attempts to get <code>obj2</code> at index <code>i</code>, but incorrectly is given
|
||
<code>obj3</code>, when instead the get should fail.</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<p>By introducing a monotonically increasing generation counter to the collection,
|
||
associating each element in the collection with the generation when it was
|
||
inserted, and getting elements from the collection with the <em>pair</em> of index and
|
||
the generation at the time when the element was inserted, then we can solve the
|
||
aforementioned ABA problem. When indexing into the collection, if the index
|
||
pair's generation does not match the generation of the element at that index,
|
||
then the operation fails.</p>
|
||
<h2 id="features" class="section-header"><a href="#features">Features</a></h2>
|
||
<ul>
|
||
<li>Zero <code>unsafe</code></li>
|
||
<li>Well tested, including quickchecks</li>
|
||
<li><code>no_std</code> compatibility</li>
|
||
<li>All the trait implementations you expect: <code>IntoIterator</code>, <code>FromIterator</code>,
|
||
<code>Extend</code>, etc...</li>
|
||
</ul>
|
||
<h2 id="usage" class="section-header"><a href="#usage">Usage</a></h2>
|
||
<p>First, add <code>generational-arena</code> to your <code>Cargo.toml</code>:</p>
|
||
<pre><code class="language-toml">[dependencies]
|
||
generational-arena = "0.1"
|
||
</code></pre>
|
||
<p>Then, import the crate and use the
|
||
<a href="./struct.Arena.html"><code>generational_arena::Arena</code></a> type!</p>
|
||
|
||
<div class="example-wrap"><pre class="rust rust-example-rendered">
|
||
<span class="kw">extern</span> <span class="kw">crate</span> <span class="ident">generational_arena</span>;
|
||
<span class="kw">use</span> <span class="ident">generational_arena</span>::<span class="ident">Arena</span>;
|
||
|
||
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">arena</span> <span class="op">=</span> <span class="ident">Arena</span>::<span class="ident">new</span>();
|
||
|
||
<span class="comment">// Insert some elements into the arena.</span>
|
||
<span class="kw">let</span> <span class="ident">rza</span> <span class="op">=</span> <span class="ident">arena</span>.<span class="ident">insert</span>(<span class="string">"Robert Fitzgerald Diggs"</span>);
|
||
<span class="kw">let</span> <span class="ident">gza</span> <span class="op">=</span> <span class="ident">arena</span>.<span class="ident">insert</span>(<span class="string">"Gary Grice"</span>);
|
||
<span class="kw">let</span> <span class="ident">bill</span> <span class="op">=</span> <span class="ident">arena</span>.<span class="ident">insert</span>(<span class="string">"Bill Gates"</span>);
|
||
|
||
<span class="comment">// Inserted elements can be accessed infallibly via indexing (and missing</span>
|
||
<span class="comment">// entries will panic).</span>
|
||
<span class="macro">assert_eq</span><span class="macro">!</span>(<span class="ident">arena</span>[<span class="ident">rza</span>], <span class="string">"Robert Fitzgerald Diggs"</span>);
|
||
|
||
<span class="comment">// Alternatively, the `get` and `get_mut` methods provide fallible lookup.</span>
|
||
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">genius</span>) <span class="op">=</span> <span class="ident">arena</span>.<span class="ident">get</span>(<span class="ident">gza</span>) {
|
||
<span class="macro">println</span><span class="macro">!</span>(<span class="string">"The gza gza genius: {}"</span>, <span class="ident">genius</span>);
|
||
}
|
||
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">val</span>) <span class="op">=</span> <span class="ident">arena</span>.<span class="ident">get_mut</span>(<span class="ident">bill</span>) {
|
||
<span class="kw-2">*</span><span class="ident">val</span> <span class="op">=</span> <span class="string">"Bill Gates doesn't belong in this set..."</span>;
|
||
}
|
||
|
||
<span class="comment">// We can remove elements.</span>
|
||
<span class="ident">arena</span>.<span class="ident">remove</span>(<span class="ident">bill</span>);
|
||
|
||
<span class="comment">// Insert a new one.</span>
|
||
<span class="kw">let</span> <span class="ident">murray</span> <span class="op">=</span> <span class="ident">arena</span>.<span class="ident">insert</span>(<span class="string">"Bill Murray"</span>);
|
||
|
||
<span class="comment">// The arena does not contain `bill` anymore, but it does contain `murray`, even</span>
|
||
<span class="comment">// though they are almost certainly at the same index within the arena in</span>
|
||
<span class="comment">// practice. Ambiguities are resolved with an associated generation tag.</span>
|
||
<span class="macro">assert</span><span class="macro">!</span>(<span class="op">!</span><span class="ident">arena</span>.<span class="ident">contains</span>(<span class="ident">bill</span>));
|
||
<span class="macro">assert</span><span class="macro">!</span>(<span class="ident">arena</span>.<span class="ident">contains</span>(<span class="ident">murray</span>));
|
||
|
||
<span class="comment">// Iterate over everything inside the arena.</span>
|
||
<span class="kw">for</span> (<span class="ident">idx</span>, <span class="ident">value</span>) <span class="kw">in</span> <span class="kw-2">&</span><span class="ident">arena</span> {
|
||
<span class="macro">println</span><span class="macro">!</span>(<span class="string">"{:?} is at {:?}"</span>, <span class="ident">value</span>, <span class="ident">idx</span>);
|
||
}</pre></div>
|
||
<h2 id="no_std" class="section-header"><a href="#no_std"><code>no_std</code></a></h2>
|
||
<p>To enable <code>no_std</code> compatibility, disable the on-by-default "std" feature. This
|
||
currently requires nightly Rust and <code>feature(alloc)</code> to get access to <code>Vec</code>.</p>
|
||
<pre><code class="language-toml">[dependencies]
|
||
generational-arena = { version = "0.2", default-features = false }
|
||
</code></pre>
|
||
<h3 id="serialization-and-deserialization-with-serde" class="section-header"><a href="#serialization-and-deserialization-with-serde">Serialization and Deserialization with <a href="https://crates.io/crates/serde"><code>serde</code></a></a></h3>
|
||
<p>To enable serialization/deserialization support, enable the "serde" feature.</p>
|
||
<pre><code class="language-toml">[dependencies]
|
||
generational-arena = { version = "0.2", features = ["serde"] }
|
||
</code></pre>
|
||
</div><h2 id='structs' class='section-header'><a href="#structs">Structs</a></h2>
|
||
<table><tr class='module-item'><td><a class="struct" href="struct.Arena.html" title='generational_arena::Arena struct'>Arena</a></td><td class='docblock-short'><p>The <code>Arena</code> allows inserting and removing elements that are referred to by
|
||
<code>Index</code>.</p>
|
||
</td></tr><tr class='module-item'><td><a class="struct" href="struct.Drain.html" title='generational_arena::Drain struct'>Drain</a></td><td class='docblock-short'><p>An iterator that removes elements from the arena.</p>
|
||
</td></tr><tr class='module-item'><td><a class="struct" href="struct.Index.html" title='generational_arena::Index struct'>Index</a></td><td class='docblock-short'><p>An index (and generation) into an <code>Arena</code>.</p>
|
||
</td></tr><tr class='module-item'><td><a class="struct" href="struct.IntoIter.html" title='generational_arena::IntoIter struct'>IntoIter</a></td><td class='docblock-short'><p>An iterator over the elements in an arena.</p>
|
||
</td></tr><tr class='module-item'><td><a class="struct" href="struct.Iter.html" title='generational_arena::Iter struct'>Iter</a></td><td class='docblock-short'><p>An iterator over shared references to the elements in an arena.</p>
|
||
</td></tr><tr class='module-item'><td><a class="struct" href="struct.IterMut.html" title='generational_arena::IterMut struct'>IterMut</a></td><td class='docblock-short'><p>An iterator over exclusive references to elements in this arena.</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>⏎</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><p>Search multiple things at once by splitting your query with comma (e.g., <code>str,u8</code> or <code>String,struct:Vec,test</code>)</p></div></div></aside><script>window.rootPath = "../";window.currentCrate = "generational_arena";</script><script src="../aliases.js"></script><script src="../main.js"></script><script defer src="../search-index.js"></script></body></html> |