Auto Generated Documentation
This commit is contained in:
@@ -0,0 +1 @@
|
||||
<!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="List of all items in this crate"><title>List of all items in this crate</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../static.files/rustdoc-46132b98.css"><meta name="rustdoc-vars" data-root-path="../" data-static-root-path="../static.files/" data-current-crate="once_cell" data-themes="" data-resource-suffix="" data-rustdoc-version="1.85.1 (4eb161250 2025-03-15)" data-channel="1.85.1" data-search-js="search-75f5ac3e.js" data-settings-js="settings-0f613d39.js" ><script src="../static.files/storage-59e33391.js"></script><script defer src="../static.files/main-5f194d8c.js"></script><noscript><link rel="stylesheet" href="../static.files/noscript-893ab5e7.css"></noscript><link rel="alternate icon" type="image/png" href="../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../static.files/favicon-044be391.svg"></head><body class="rustdoc mod sys"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../once_cell/index.html">once_<wbr>cell</a><span class="version">1.21.3</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h3><a href="#structs">Crate Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li></ul></section><div id="rustdoc-modnav"></div></div></nav><div class="sidebar-resizer"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><h1>List of all items</h1><h3 id="structs">Structs</h3><ul class="all-items"><li><a href="race/struct.OnceBool.html">race::OnceBool</a></li><li><a href="race/struct.OnceBox.html">race::OnceBox</a></li><li><a href="race/struct.OnceNonZeroUsize.html">race::OnceNonZeroUsize</a></li><li><a href="race/struct.OnceRef.html">race::OnceRef</a></li><li><a href="sync/struct.Lazy.html">sync::Lazy</a></li><li><a href="sync/struct.OnceCell.html">sync::OnceCell</a></li><li><a href="unsync/struct.Lazy.html">unsync::Lazy</a></li><li><a href="unsync/struct.OnceCell.html">unsync::OnceCell</a></li></ul></section></div></main></body></html>
|
||||
@@ -0,0 +1,288 @@
|
||||
<!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="Overview"><title>once_cell - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../static.files/rustdoc-46132b98.css"><meta name="rustdoc-vars" data-root-path="../" data-static-root-path="../static.files/" data-current-crate="once_cell" data-themes="" data-resource-suffix="" data-rustdoc-version="1.85.1 (4eb161250 2025-03-15)" data-channel="1.85.1" data-search-js="search-75f5ac3e.js" data-settings-js="settings-0f613d39.js" ><script src="../static.files/storage-59e33391.js"></script><script defer src="../crates.js"></script><script defer src="../static.files/main-5f194d8c.js"></script><noscript><link rel="stylesheet" href="../static.files/noscript-893ab5e7.css"></noscript><link rel="alternate icon" type="image/png" href="../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../static.files/favicon-044be391.svg"></head><body class="rustdoc mod crate"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../once_cell/index.html">once_<wbr>cell</a><span class="version">1.21.3</span></h2></div><div class="sidebar-elems"><ul class="block"><li><a id="all-types" href="all.html">All Items</a></li></ul><section id="rustdoc-toc"><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#overview" title="Overview">Overview</a></li><li><a href="#recipes" title="Recipes">Recipes</a><ul><li><a href="#safe-initialization-of-global-data" title="Safe Initialization of Global Data">Safe Initialization of Global Data</a></li><li><a href="#lazy-initialized-global-data" title="Lazy Initialized Global Data">Lazy Initialized Global Data</a></li><li><a href="#general-purpose-lazy-evaluation" title="General purpose lazy evaluation">General purpose lazy evaluation</a></li><li><a href="#lazily-compiled-regex" title="Lazily Compiled Regex">Lazily Compiled Regex</a></li><li><a href="#runtime-include_bytes" title="Runtime `include_bytes!`">Runtime <code>include_bytes!</code></a></li><li><a href="#lateinit" title="`lateinit`"><code>lateinit</code></a></li></ul></li><li><a href="#comparison-with-std" title="Comparison with std">Comparison with std</a></li><li><a href="#minimum-supported-rustc-version" title="Minimum Supported `rustc` Version">Minimum Supported <code>rustc</code> Version</a></li><li><a href="#implementation-details" title="Implementation details">Implementation details</a></li><li><a href="#faq" title="F.A.Q.">F.A.Q.</a></li><li><a href="#related-crates" title="Related crates">Related crates</a></li></ul><h3><a href="#modules">Crate Items</a></h3><ul class="block"><li><a href="#modules" title="Modules">Modules</a></li></ul></section><div id="rustdoc-modnav"></div></div></nav><div class="sidebar-resizer"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><h1>Crate <span>once_cell</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../src/once_cell/lib.rs.html#1-1412">Source</a> </span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><h2 id="overview"><a class="doc-anchor" href="#overview">§</a>Overview</h2>
|
||||
<p><code>once_cell</code> provides two new cell-like types, <a href="unsync/struct.OnceCell.html"><code>unsync::OnceCell</code></a> and
|
||||
<a href="sync/struct.OnceCell.html"><code>sync::OnceCell</code></a>. A <code>OnceCell</code> might store arbitrary non-<code>Copy</code> types, can
|
||||
be assigned to at most once and provides direct access to the stored
|
||||
contents. The core API looks <em>roughly</em> like this (and there’s much more
|
||||
inside, read on!):</p>
|
||||
|
||||
<div class="example-wrap ignore"><a href="#" class="tooltip" title="This example is not tested">ⓘ</a><pre class="rust rust-example-rendered"><code><span class="kw">impl</span><T> OnceCell<T> {
|
||||
<span class="kw">const fn </span>new() -> OnceCell<T> { ... }
|
||||
<span class="kw">fn </span>set(<span class="kw-2">&</span><span class="self">self</span>, value: T) -> <span class="prelude-ty">Result</span><(), T> { ... }
|
||||
<span class="kw">fn </span>get(<span class="kw-2">&</span><span class="self">self</span>) -> <span class="prelude-ty">Option</span><<span class="kw-2">&</span>T> { ... }
|
||||
}</code></pre></div>
|
||||
<p>Note that, like with <a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html"><code>RefCell</code></a> and <a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html"><code>Mutex</code></a>, the <code>set</code> method requires
|
||||
only a shared reference. Because of the single assignment restriction <code>get</code>
|
||||
can return a <code>&T</code> instead of <code>Ref<T></code> or <code>MutexGuard<T></code>.</p>
|
||||
<p>The <code>sync</code> flavor is thread-safe (that is, implements the <a href="https://doc.rust-lang.org/std/marker/trait.Sync.html"><code>Sync</code></a> trait),
|
||||
while the <code>unsync</code> one is not.</p>
|
||||
<h2 id="recipes"><a class="doc-anchor" href="#recipes">§</a>Recipes</h2>
|
||||
<p><code>OnceCell</code> might be useful for a variety of patterns.</p>
|
||||
<h3 id="safe-initialization-of-global-data"><a class="doc-anchor" href="#safe-initialization-of-global-data">§</a>Safe Initialization of Global Data</h3>
|
||||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>std::{env, io};
|
||||
|
||||
<span class="kw">use </span>once_cell::sync::OnceCell;
|
||||
|
||||
<span class="attr">#[derive(Debug)]
|
||||
</span><span class="kw">pub struct </span>Logger {
|
||||
<span class="comment">// ...
|
||||
</span>}
|
||||
<span class="kw">static </span>INSTANCE: OnceCell<Logger> = OnceCell::new();
|
||||
|
||||
<span class="kw">impl </span>Logger {
|
||||
<span class="kw">pub fn </span>global() -> <span class="kw-2">&</span><span class="lifetime">'static </span>Logger {
|
||||
INSTANCE.get().expect(<span class="string">"logger is not initialized"</span>)
|
||||
}
|
||||
|
||||
<span class="kw">fn </span>from_cli(args: env::Args) -> <span class="prelude-ty">Result</span><Logger, std::io::Error> {
|
||||
<span class="comment">// ...
|
||||
</span>}
|
||||
}
|
||||
|
||||
<span class="kw">fn </span>main() {
|
||||
<span class="kw">let </span>logger = Logger::from_cli(env::args()).unwrap();
|
||||
INSTANCE.set(logger).unwrap();
|
||||
<span class="comment">// use `Logger::global()` from now on
|
||||
</span>}</code></pre></div>
|
||||
<h3 id="lazy-initialized-global-data"><a class="doc-anchor" href="#lazy-initialized-global-data">§</a>Lazy Initialized Global Data</h3>
|
||||
<p>This is essentially the <code>lazy_static!</code> macro, but without a macro.</p>
|
||||
|
||||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>std::{sync::Mutex, collections::HashMap};
|
||||
|
||||
<span class="kw">use </span>once_cell::sync::OnceCell;
|
||||
|
||||
<span class="kw">fn </span>global_data() -> <span class="kw-2">&</span><span class="lifetime">'static </span>Mutex<HashMap<i32, String>> {
|
||||
<span class="kw">static </span>INSTANCE: OnceCell<Mutex<HashMap<i32, String>>> = OnceCell::new();
|
||||
INSTANCE.get_or_init(|| {
|
||||
<span class="kw">let </span><span class="kw-2">mut </span>m = HashMap::new();
|
||||
m.insert(<span class="number">13</span>, <span class="string">"Spica"</span>.to_string());
|
||||
m.insert(<span class="number">74</span>, <span class="string">"Hoyten"</span>.to_string());
|
||||
Mutex::new(m)
|
||||
})
|
||||
}</code></pre></div>
|
||||
<p>There are also the <a href="sync/struct.Lazy.html"><code>sync::Lazy</code></a> and <a href="unsync/struct.Lazy.html"><code>unsync::Lazy</code></a> convenience types to
|
||||
streamline this pattern:</p>
|
||||
|
||||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>std::{sync::Mutex, collections::HashMap};
|
||||
<span class="kw">use </span>once_cell::sync::Lazy;
|
||||
|
||||
<span class="kw">static </span>GLOBAL_DATA: Lazy<Mutex<HashMap<i32, String>>> = Lazy::new(|| {
|
||||
<span class="kw">let </span><span class="kw-2">mut </span>m = HashMap::new();
|
||||
m.insert(<span class="number">13</span>, <span class="string">"Spica"</span>.to_string());
|
||||
m.insert(<span class="number">74</span>, <span class="string">"Hoyten"</span>.to_string());
|
||||
Mutex::new(m)
|
||||
});
|
||||
|
||||
<span class="kw">fn </span>main() {
|
||||
<span class="macro">println!</span>(<span class="string">"{:?}"</span>, GLOBAL_DATA.lock().unwrap());
|
||||
}</code></pre></div>
|
||||
<p>Note that the variable that holds <code>Lazy</code> is declared as <code>static</code>, <em>not</em>
|
||||
<code>const</code>. This is important: using <code>const</code> instead compiles, but works wrong.</p>
|
||||
<h3 id="general-purpose-lazy-evaluation"><a class="doc-anchor" href="#general-purpose-lazy-evaluation">§</a>General purpose lazy evaluation</h3>
|
||||
<p>Unlike <code>lazy_static!</code>, <code>Lazy</code> works with local variables.</p>
|
||||
|
||||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>once_cell::unsync::Lazy;
|
||||
|
||||
<span class="kw">fn </span>main() {
|
||||
<span class="kw">let </span>ctx = <span class="macro">vec!</span>[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];
|
||||
<span class="kw">let </span>thunk = Lazy::new(|| {
|
||||
ctx.iter().sum::<i32>()
|
||||
});
|
||||
<span class="macro">assert_eq!</span>(<span class="kw-2">*</span>thunk, <span class="number">6</span>);
|
||||
}</code></pre></div>
|
||||
<p>If you need a lazy field in a struct, you probably should use <code>OnceCell</code>
|
||||
directly, because that will allow you to access <code>self</code> during
|
||||
initialization.</p>
|
||||
|
||||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>std::{fs, path::PathBuf};
|
||||
|
||||
<span class="kw">use </span>once_cell::unsync::OnceCell;
|
||||
|
||||
<span class="kw">struct </span>Ctx {
|
||||
config_path: PathBuf,
|
||||
config: OnceCell<String>,
|
||||
}
|
||||
|
||||
<span class="kw">impl </span>Ctx {
|
||||
<span class="kw">pub fn </span>get_config(<span class="kw-2">&</span><span class="self">self</span>) -> <span class="prelude-ty">Result</span><<span class="kw-2">&</span>str, std::io::Error> {
|
||||
<span class="kw">let </span>cfg = <span class="self">self</span>.config.get_or_try_init(|| {
|
||||
fs::read_to_string(<span class="kw-2">&</span><span class="self">self</span>.config_path)
|
||||
})<span class="question-mark">?</span>;
|
||||
<span class="prelude-val">Ok</span>(cfg.as_str())
|
||||
}
|
||||
}</code></pre></div>
|
||||
<h3 id="lazily-compiled-regex"><a class="doc-anchor" href="#lazily-compiled-regex">§</a>Lazily Compiled Regex</h3>
|
||||
<p>This is a <code>regex!</code> macro which takes a string literal and returns an
|
||||
<em>expression</em> that evaluates to a <code>&'static Regex</code>:</p>
|
||||
|
||||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="macro">macro_rules!</span> regex {
|
||||
(<span class="macro-nonterminal">$re</span>:literal $(,)<span class="question-mark">?</span>) => {{
|
||||
<span class="kw">static </span>RE: once_cell::sync::OnceCell<regex::Regex> = once_cell::sync::OnceCell::new();
|
||||
RE.get_or_init(|| regex::Regex::new(<span class="macro-nonterminal">$re</span>).unwrap())
|
||||
}};
|
||||
}</code></pre></div>
|
||||
<p>This macro can be useful to avoid the “compile regex on every loop
|
||||
iteration” problem.</p>
|
||||
<h3 id="runtime-include_bytes"><a class="doc-anchor" href="#runtime-include_bytes">§</a>Runtime <code>include_bytes!</code></h3>
|
||||
<p>The <code>include_bytes</code> macro is useful to include test resources, but it slows
|
||||
down test compilation a lot. An alternative is to load the resources at
|
||||
runtime:</p>
|
||||
|
||||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>std::path::Path;
|
||||
|
||||
<span class="kw">use </span>once_cell::sync::OnceCell;
|
||||
|
||||
<span class="kw">pub struct </span>TestResource {
|
||||
path: <span class="kw-2">&</span><span class="lifetime">'static </span>str,
|
||||
cell: OnceCell<Vec<u8>>,
|
||||
}
|
||||
|
||||
<span class="kw">impl </span>TestResource {
|
||||
<span class="kw">pub const fn </span>new(path: <span class="kw-2">&</span><span class="lifetime">'static </span>str) -> TestResource {
|
||||
TestResource { path, cell: OnceCell::new() }
|
||||
}
|
||||
<span class="kw">pub fn </span>bytes(<span class="kw-2">&</span><span class="self">self</span>) -> <span class="kw-2">&</span>[u8] {
|
||||
<span class="self">self</span>.cell.get_or_init(|| {
|
||||
<span class="kw">let </span>dir = std::env::var(<span class="string">"CARGO_MANIFEST_DIR"</span>).unwrap();
|
||||
<span class="kw">let </span>path = Path::new(dir.as_str()).join(<span class="self">self</span>.path);
|
||||
std::fs::read(<span class="kw-2">&</span>path).unwrap_or_else(|_err| {
|
||||
<span class="macro">panic!</span>(<span class="string">"failed to load test resource: {}"</span>, path.display())
|
||||
})
|
||||
}).as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
<span class="kw">static </span>TEST_IMAGE: TestResource = TestResource::new(<span class="string">"test_data/lena.png"</span>);
|
||||
|
||||
<span class="attr">#[test]
|
||||
</span><span class="kw">fn </span>test_sobel_filter() {
|
||||
<span class="kw">let </span>rgb: <span class="kw-2">&</span>[u8] = TEST_IMAGE.bytes();
|
||||
<span class="comment">// ...
|
||||
</span>}</code></pre></div>
|
||||
<h3 id="lateinit"><a class="doc-anchor" href="#lateinit">§</a><code>lateinit</code></h3>
|
||||
<p><code>LateInit</code> type for delayed initialization. It is reminiscent of Kotlin’s
|
||||
<code>lateinit</code> keyword and allows construction of cyclic data structures:</p>
|
||||
|
||||
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">use </span>once_cell::sync::OnceCell;
|
||||
|
||||
<span class="kw">pub struct </span>LateInit<T> { cell: OnceCell<T> }
|
||||
|
||||
<span class="kw">impl</span><T> LateInit<T> {
|
||||
<span class="kw">pub fn </span>init(<span class="kw-2">&</span><span class="self">self</span>, value: T) {
|
||||
<span class="macro">assert!</span>(<span class="self">self</span>.cell.set(value).is_ok())
|
||||
}
|
||||
}
|
||||
|
||||
<span class="kw">impl</span><T> Default <span class="kw">for </span>LateInit<T> {
|
||||
<span class="kw">fn </span>default() -> <span class="self">Self </span>{ LateInit { cell: OnceCell::default() } }
|
||||
}
|
||||
|
||||
<span class="kw">impl</span><T> std::ops::Deref <span class="kw">for </span>LateInit<T> {
|
||||
<span class="kw">type </span>Target = T;
|
||||
<span class="kw">fn </span>deref(<span class="kw-2">&</span><span class="self">self</span>) -> <span class="kw-2">&</span>T {
|
||||
<span class="self">self</span>.cell.get().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
<span class="attr">#[derive(Default)]
|
||||
</span><span class="kw">struct </span>A<<span class="lifetime">'a</span>> {
|
||||
b: LateInit<<span class="kw-2">&</span><span class="lifetime">'a </span>B<<span class="lifetime">'a</span>>>,
|
||||
}
|
||||
|
||||
<span class="attr">#[derive(Default)]
|
||||
</span><span class="kw">struct </span>B<<span class="lifetime">'a</span>> {
|
||||
a: LateInit<<span class="kw-2">&</span><span class="lifetime">'a </span>A<<span class="lifetime">'a</span>>>
|
||||
}
|
||||
|
||||
|
||||
<span class="kw">fn </span>build_cycle() {
|
||||
<span class="kw">let </span>a = A::default();
|
||||
<span class="kw">let </span>b = B::default();
|
||||
a.b.init(<span class="kw-2">&</span>b);
|
||||
b.a.init(<span class="kw-2">&</span>a);
|
||||
|
||||
<span class="kw">let </span>_a = <span class="kw-2">&</span>a.b.a.b.a;
|
||||
}</code></pre></div>
|
||||
<h2 id="comparison-with-std"><a class="doc-anchor" href="#comparison-with-std">§</a>Comparison with std</h2><div><table><thead><tr><th><code>!Sync</code> types</th><th>Access Mode</th><th>Drawbacks</th></tr></thead><tbody>
|
||||
<tr><td><code>Cell<T></code></td><td><code>T</code></td><td>requires <code>T: Copy</code> for <code>get</code></td></tr>
|
||||
<tr><td><code>RefCell<T></code></td><td><code>RefMut<T></code> / <code>Ref<T></code></td><td>may panic at runtime</td></tr>
|
||||
<tr><td><code>unsync::OnceCell<T></code></td><td><code>&T</code></td><td>assignable only once</td></tr>
|
||||
</tbody></table>
|
||||
</div><div><table><thead><tr><th><code>Sync</code> types</th><th>Access Mode</th><th>Drawbacks</th></tr></thead><tbody>
|
||||
<tr><td><code>AtomicT</code></td><td><code>T</code></td><td>works only with certain <code>Copy</code> types</td></tr>
|
||||
<tr><td><code>Mutex<T></code></td><td><code>MutexGuard<T></code></td><td>may deadlock at runtime, may block the thread</td></tr>
|
||||
<tr><td><code>sync::OnceCell<T></code></td><td><code>&T</code></td><td>assignable only once, may block the thread</td></tr>
|
||||
</tbody></table>
|
||||
</div>
|
||||
<p>Technically, calling <code>get_or_init</code> will also cause a panic or a deadlock if
|
||||
it recursively calls itself. However, because the assignment can happen only
|
||||
once, such cases should be more rare than equivalents with <code>RefCell</code> and
|
||||
<code>Mutex</code>.</p>
|
||||
<h2 id="minimum-supported-rustc-version"><a class="doc-anchor" href="#minimum-supported-rustc-version">§</a>Minimum Supported <code>rustc</code> Version</h2>
|
||||
<p>If only the <code>std</code>, <code>alloc</code>, or <code>race</code> features are enabled, MSRV will be
|
||||
updated conservatively, supporting at least latest 8 versions of the compiler.
|
||||
When using other features, like <code>parking_lot</code>, MSRV might be updated more
|
||||
frequently, up to the latest stable. In both cases, increasing MSRV is <em>not</em>
|
||||
considered a semver-breaking change and requires only a minor version bump.</p>
|
||||
<h2 id="implementation-details"><a class="doc-anchor" href="#implementation-details">§</a>Implementation details</h2>
|
||||
<p>The implementation is based on the
|
||||
<a href="https://github.com/rust-lang-nursery/lazy-static.rs/"><code>lazy_static</code></a> and
|
||||
<a href="https://github.com/indiv0/lazycell/"><code>lazy_cell</code></a> crates and
|
||||
<a href="https://doc.rust-lang.org/std/sync/struct.Once.html"><code>std::sync::Once</code></a>. In some sense, <code>once_cell</code> just streamlines and unifies
|
||||
those APIs.</p>
|
||||
<p>To implement a sync flavor of <code>OnceCell</code>, this crates uses either a custom
|
||||
re-implementation of <code>std::sync::Once</code> or <code>parking_lot::Mutex</code>. This is
|
||||
controlled by the <code>parking_lot</code> feature (disabled by default). Performance
|
||||
is the same for both cases, but the <code>parking_lot</code> based <code>OnceCell<T></code> is
|
||||
smaller by up to 16 bytes.</p>
|
||||
<p>This crate uses <code>unsafe</code>.</p>
|
||||
<h2 id="faq"><a class="doc-anchor" href="#faq">§</a>F.A.Q.</h2>
|
||||
<p><strong>Should I use the sync or unsync flavor?</strong></p>
|
||||
<p>Because Rust compiler checks thread safety for you, it’s impossible to
|
||||
accidentally use <code>unsync</code> where <code>sync</code> is required. So, use <code>unsync</code> in
|
||||
single-threaded code and <code>sync</code> in multi-threaded. It’s easy to switch
|
||||
between the two if code becomes multi-threaded later.</p>
|
||||
<p>At the moment, <code>unsync</code> has an additional benefit that reentrant
|
||||
initialization causes a panic, which might be easier to debug than a
|
||||
deadlock.</p>
|
||||
<p><strong>Does this crate support async?</strong></p>
|
||||
<p>No, but you can use
|
||||
<a href="https://crates.io/crates/async_once_cell"><code>async_once_cell</code></a> instead.</p>
|
||||
<p><strong>Does this crate support <code>no_std</code>?</strong></p>
|
||||
<p>Yes, but with caveats. <code>OnceCell</code> is a synchronization primitive which
|
||||
<em>semantically</em> relies on blocking. <code>OnceCell</code> guarantees that at most one
|
||||
<code>f</code> will be called to compute the value. If two threads of execution call
|
||||
<code>get_or_init</code> concurrently, one of them has to wait.</p>
|
||||
<p>Waiting fundamentally requires OS support. Execution environment needs to
|
||||
understand who waits on whom to prevent deadlocks due to priority inversion.
|
||||
You <em>could</em> make code to compile by blindly using pure spinlocks, but the
|
||||
runtime behavior would be subtly wrong.</p>
|
||||
<p>Given these constraints, <code>once_cell</code> provides the following options:</p>
|
||||
<ul>
|
||||
<li>The <code>race</code> module provides similar, but distinct synchronization primitive
|
||||
which is compatible with <code>no_std</code>. With <code>race</code>, the <code>f</code> function can be
|
||||
called multiple times by different threads, but only one thread will win
|
||||
to install the value.</li>
|
||||
<li><code>critical-section</code> feature (with a <code>-</code>, not <code>_</code>) uses <code>critical_section</code>
|
||||
to implement blocking.</li>
|
||||
</ul>
|
||||
<p><strong>Can I bring my own mutex?</strong></p>
|
||||
<p>There is <a href="https://crates.io/crates/generic_once_cell">generic_once_cell</a> to
|
||||
allow just that.</p>
|
||||
<p><strong>Should I use <code>std::cell::OnceCell</code>, <code>once_cell</code>, or <code>lazy_static</code>?</strong></p>
|
||||
<p>If you can use <code>std</code> version (your MSRV is at least 1.70, and you don’t need
|
||||
extra features <code>once_cell</code> provides), use <code>std</code>. Otherwise, use <code>once_cell</code>.
|
||||
Don’t use <code>lazy_static</code>.</p>
|
||||
<h2 id="related-crates"><a class="doc-anchor" href="#related-crates">§</a>Related crates</h2>
|
||||
<ul>
|
||||
<li>Most of this crate’s functionality is available in <code>std</code> starting with
|
||||
Rust 1.70. See <code>std::cell::OnceCell</code> and <code>std::sync::OnceLock</code>.</li>
|
||||
<li><a href="https://github.com/niklasf/double-checked-cell">double-checked-cell</a></li>
|
||||
<li><a href="https://crates.io/crates/lazy-init">lazy-init</a></li>
|
||||
<li><a href="https://crates.io/crates/lazycell">lazycell</a></li>
|
||||
<li><a href="https://crates.io/crates/mitochondria">mitochondria</a></li>
|
||||
<li><a href="https://crates.io/crates/lazy_static">lazy_static</a></li>
|
||||
<li><a href="https://crates.io/crates/async_once_cell">async_once_cell</a></li>
|
||||
<li><a href="https://crates.io/crates/generic_once_cell">generic_once_cell</a> (bring
|
||||
your own mutex)</li>
|
||||
</ul>
|
||||
</div></details><h2 id="modules" class="section-header">Modules<a href="#modules" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="mod" href="race/index.html" title="mod once_cell::race">race</a></div><div class="desc docblock-short">Thread-safe, non-blocking, “first one wins” flavor of <code>OnceCell</code>.</div></li><li><div class="item-name"><a class="mod" href="sync/index.html" title="mod once_cell::sync">sync</a></div><div class="desc docblock-short">Thread-safe, blocking version of <code>OnceCell</code>.</div></li><li><div class="item-name"><a class="mod" href="unsync/index.html" title="mod once_cell::unsync">unsync</a></div><div class="desc docblock-short">Single-threaded version of <code>OnceCell</code>.</div></li></ul></section></div></main></body></html>
|
||||
@@ -0,0 +1,17 @@
|
||||
<!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="Thread-safe, non-blocking, “first one wins” flavor of `OnceCell`."><title>once_cell::race - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-46132b98.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="once_cell" data-themes="" data-resource-suffix="" data-rustdoc-version="1.85.1 (4eb161250 2025-03-15)" data-channel="1.85.1" data-search-js="search-75f5ac3e.js" data-settings-js="settings-0f613d39.js" ><script src="../../static.files/storage-59e33391.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../static.files/main-5f194d8c.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-893ab5e7.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../once_cell/index.html">once_<wbr>cell</a><span class="version">1.21.3</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module race</a></h2><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#atomic-orderings" title="Atomic orderings">Atomic orderings</a></li></ul><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li></ul></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="../index.html">In crate once_<wbr>cell</a></h2></div></div></nav><div class="sidebar-resizer"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><span class="rustdoc-breadcrumbs"><a href="../index.html">once_cell</a></span><h1>Module <span>race</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/once_cell/race.rs.html#1-498">Source</a> </span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Thread-safe, non-blocking, “first one wins” flavor of <code>OnceCell</code>.</p>
|
||||
<p>If two threads race to initialize a type from the <code>race</code> module, they
|
||||
don’t block, execute initialization function together, but only one of
|
||||
them stores the result.</p>
|
||||
<p>This module does not require <code>std</code> feature.</p>
|
||||
<h2 id="atomic-orderings"><a class="doc-anchor" href="#atomic-orderings">§</a>Atomic orderings</h2>
|
||||
<p>All types in this module use <code>Acquire</code> and <code>Release</code>
|
||||
<a href="https://doc.rust-lang.org/1.85.1/core/sync/atomic/enum.Ordering.html" title="enum core::sync::atomic::Ordering">atomic orderings</a> for all their operations. While this is not
|
||||
strictly necessary for types other than <code>OnceBox</code>, it is useful for users as
|
||||
it allows them to be certain that after <code>get</code> or <code>get_or_init</code> returns on
|
||||
one thread, any side-effects caused by the setter thread prior to them
|
||||
calling <code>set</code> or <code>get_or_init</code> will be made visible to that thread; without
|
||||
it, it’s possible for it to appear as if they haven’t happened yet from the
|
||||
getter thread’s perspective. This is an acceptable tradeoff to make since
|
||||
<code>Acquire</code> and <code>Release</code> have very little performance overhead on most
|
||||
architectures versus <code>Relaxed</code>.</p>
|
||||
</div></details><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="struct" href="struct.OnceBool.html" title="struct once_cell::race::OnceBool">Once<wbr>Bool</a></div><div class="desc docblock-short">A thread-safe cell which can be written to only once.</div></li><li><div class="item-name"><a class="struct" href="struct.OnceBox.html" title="struct once_cell::race::OnceBox">OnceBox</a></div><div class="desc docblock-short">A thread-safe cell which can be written to only once.</div></li><li><div class="item-name"><a class="struct" href="struct.OnceNonZeroUsize.html" title="struct once_cell::race::OnceNonZeroUsize">Once<wbr>NonZero<wbr>Usize</a></div><div class="desc docblock-short">A thread-safe cell which can be written to only once.</div></li><li><div class="item-name"><a class="struct" href="struct.OnceRef.html" title="struct once_cell::race::OnceRef">OnceRef</a></div><div class="desc docblock-short">A thread-safe cell which can be written to only once.</div></li></ul></section></div></main></body></html>
|
||||
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0;URL=../../../once_cell/race/struct.OnceBox.html">
|
||||
<title>Redirection</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to <a href="../../../once_cell/race/struct.OnceBox.html">../../../once_cell/race/struct.OnceBox.html</a>...</p>
|
||||
<script>location.replace("../../../once_cell/race/struct.OnceBox.html" + location.search + location.hash);</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
window.SIDEBAR_ITEMS = {"struct":["OnceBool","OnceBox","OnceNonZeroUsize","OnceRef"]};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
window.SIDEBAR_ITEMS = {"mod":["race","sync","unsync"]};
|
||||
@@ -0,0 +1,2 @@
|
||||
<!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="Thread-safe, blocking version of `OnceCell`."><title>once_cell::sync - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-46132b98.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="once_cell" data-themes="" data-resource-suffix="" data-rustdoc-version="1.85.1 (4eb161250 2025-03-15)" data-channel="1.85.1" data-search-js="search-75f5ac3e.js" data-settings-js="settings-0f613d39.js" ><script src="../../static.files/storage-59e33391.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../static.files/main-5f194d8c.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-893ab5e7.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../once_cell/index.html">once_<wbr>cell</a><span class="version">1.21.3</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module sync</a></h2><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li></ul></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="../index.html">In crate once_<wbr>cell</a></h2></div></div></nav><div class="sidebar-resizer"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><span class="rustdoc-breadcrumbs"><a href="../index.html">once_cell</a></span><h1>Module <span>sync</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/once_cell/lib.rs.html#863">Source</a> </span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Thread-safe, blocking version of <code>OnceCell</code>.</p>
|
||||
</div></details><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="struct" href="struct.Lazy.html" title="struct once_cell::sync::Lazy">Lazy</a></div><div class="desc docblock-short">A value which is initialized on the first access.</div></li><li><div class="item-name"><a class="struct" href="struct.OnceCell.html" title="struct once_cell::sync::OnceCell">Once<wbr>Cell</a></div><div class="desc docblock-short">A thread-safe cell which can be written to only once.</div></li></ul></section></div></main></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
window.SIDEBAR_ITEMS = {"struct":["Lazy","OnceCell"]};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
<!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="Single-threaded version of `OnceCell`."><title>once_cell::unsync - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2" crossorigin href="../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../static.files/rustdoc-46132b98.css"><meta name="rustdoc-vars" data-root-path="../../" data-static-root-path="../../static.files/" data-current-crate="once_cell" data-themes="" data-resource-suffix="" data-rustdoc-version="1.85.1 (4eb161250 2025-03-15)" data-channel="1.85.1" data-search-js="search-75f5ac3e.js" data-settings-js="settings-0f613d39.js" ><script src="../../static.files/storage-59e33391.js"></script><script defer src="../sidebar-items.js"></script><script defer src="../../static.files/main-5f194d8c.js"></script><noscript><link rel="stylesheet" href="../../static.files/noscript-893ab5e7.css"></noscript><link rel="alternate icon" type="image/png" href="../../static.files/favicon-32x32-6580c154.png"><link rel="icon" type="image/svg+xml" href="../../static.files/favicon-044be391.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle" title="show sidebar"></button></nav><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../once_cell/index.html">once_<wbr>cell</a><span class="version">1.21.3</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">Module unsync</a></h2><h3><a href="#structs">Module Items</a></h3><ul class="block"><li><a href="#structs" title="Structs">Structs</a></li></ul></section><div id="rustdoc-modnav"><h2 class="in-crate"><a href="../index.html">In crate once_<wbr>cell</a></h2></div></div></nav><div class="sidebar-resizer"></div><main><div class="width-limiter"><rustdoc-search></rustdoc-search><section id="main-content" class="content"><div class="main-heading"><span class="rustdoc-breadcrumbs"><a href="../index.html">once_cell</a></span><h1>Module <span>unsync</span><button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../src/once_cell/lib.rs.html#383">Source</a> </span></div><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Single-threaded version of <code>OnceCell</code>.</p>
|
||||
</div></details><h2 id="structs" class="section-header">Structs<a href="#structs" class="anchor">§</a></h2><ul class="item-table"><li><div class="item-name"><a class="struct" href="struct.Lazy.html" title="struct once_cell::unsync::Lazy">Lazy</a></div><div class="desc docblock-short">A value which is initialized on the first access.</div></li><li><div class="item-name"><a class="struct" href="struct.OnceCell.html" title="struct once_cell::unsync::OnceCell">Once<wbr>Cell</a></div><div class="desc docblock-short">A cell which can be written to only once. It is not thread safe.</div></li></ul></section></div></main></body></html>
|
||||
@@ -0,0 +1 @@
|
||||
window.SIDEBAR_ITEMS = {"struct":["Lazy","OnceCell"]};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user