2024-05-05 09:43:20 +00:00
<!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 . write ( ` <link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/SourceSerif4-Regular-46f98efaafac5295.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/FiraSans-Regular-018c141bf0843ffd.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/FiraSans-Medium-8f9a781e4970d388.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../static.files/SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2"> ` ) < / script > < link rel = "stylesheet" href = "../static.files/normalize-76eba96aa4d2e634.css" > < link rel = "stylesheet" href = "../static.files/rustdoc-e935ef01ae1c1829.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.78.0 (9b00956e5 2024-04-29)" data-channel = "1.78.0" data-search-js = "search-42d8da7a6b9792c2.js" data-settings-js = "settings-4313503d2e1961c2.js" > < script src = "../static.files/storage-4c98445ec4002617.js" > < / script > < script defer src = "../crates.js" > < / script > < script defer src = "../static.files/main-12cf3b4f4f9dc36d.js" > < / script > < noscript > < link rel = "stylesheet" href = "../static.files/noscript-04d5337699b92874.css" > < / noscript > < link rel = "alternate icon" type = "image/png" href = "../static.files/favicon-16x16-8b506e7a72182f1c.png" > < link rel = "alternate icon" type = "image/png" href = "../static.files/favicon-32x32-422f7d1d52889060.png" > < link rel = "icon" type = "image/svg+xml" href = "../static.files/favicon-2c020d218678b618.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_cell< / a > < span class = "version" > 1.19.0< / span > < / h2 > < / div > < div class = "sidebar-elems" > < ul class = "block" >
2024-02-13 06:38:44 +00:00
< li > < a id = "all-types" href = "all.html" > All Items< / a > < / li > < / ul > < section > < ul class = "block" > < li > < a href = "#modules" > Modules< / a > < / li > < / ul > < / section > < / div > < / nav > < div class = "sidebar-resizer" > < / div >
2024-03-27 11:12:16 +00:00
< main > < div class = "width-limiter" > < nav class = "sub" > < form class = "search-form" > < span > < / span > < div id = "sidebar-button" tabindex = "-1" > < a href = "../once_cell/all.html" title = "show sidebar" > < / a > < / div > < input class = "search-input" name = "search" aria-label = "Run search in the documentation" autocomplete = "off" spellcheck = "false" placeholder = "Click or press ‘ S’ to search, ‘ ?’ for more options…" type = "search" > < div id = "help-button" tabindex = "-1" > < a href = "../help.html" title = "help" > ?< / a > < / div > < div id = "settings-menu" tabindex = "-1" > < a href = "../settings.html" title = "settings" > < img width = "22" height = "22" alt = "Change settings" src = "../static.files/wheel-7b819b6101059cd0.svg" > < / a > < / div > < / form > < / nav > < section id = "main-content" class = "content" > < div class = "main-heading" > < h1 > Crate < a class = "mod" href = "#" > once_cell< / a > < button id = "copy-path" title = "Copy item path to clipboard" > < img src = "../static.files/clipboard-7571035ce49a181d.svg" width = "19" height = "18" alt = "Copy item path" > < / button > < / h1 > < span class = "out-of-band" > < a class = "src" href = "../src/once_cell/lib.rs.html#1-1412" > source< / a > · < button id = "toggle-all-docs" title = "collapse all docs" > [< span > − < / span > ]< / button > < / 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 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< h2 id = "recipes" > < a class = "doc-anchor" href = "#recipes" > §< / a > Recipes< / h2 >
2024-02-13 06:38:44 +00:00
< p > < code > OnceCell< / code > might be useful for a variety of patterns.< / p >
2024-03-27 11:12:16 +00:00
< h3 id = "safe-initialization-of-global-data" > < a class = "doc-anchor" href = "#safe-initialization-of-global-data" > §< / a > Safe Initialization of Global Data< / h3 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< h3 id = "lazy-initialized-global-data" > < a class = "doc-anchor" href = "#lazy-initialized-global-data" > §< / a > Lazy Initialized Global Data< / h3 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< h3 id = "general-purpose-lazy-evaluation" > < a class = "doc-anchor" href = "#general-purpose-lazy-evaluation" > §< / a > General purpose lazy evaluation< / h3 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< h3 id = "lazily-compiled-regex" > < a class = "doc-anchor" href = "#lazily-compiled-regex" > §< / a > Lazily Compiled Regex< / h3 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-05-05 09:43:20 +00:00
< div class = "example-wrap" > < pre class = "rust rust-example-rendered" > < code > < span class = "macro" > macro_rules!< / span > regex {
2024-02-13 06:38:44 +00:00
(< 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 >
2024-03-27 11:12:16 +00:00
< h3 id = "runtime-include_bytes" > < a class = "doc-anchor" href = "#runtime-include_bytes" > §< / a > Runtime < code > include_bytes!< / code > < / h3 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< h3 id = "lateinit" > < a class = "doc-anchor" href = "#lateinit" > §< / a > < code > lateinit< / code > < / h3 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< 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 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< h2 id = "minimum-supported-rustc-version" > < a class = "doc-anchor" href = "#minimum-supported-rustc-version" > §< / a > Minimum Supported < code > rustc< / code > Version< / h2 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< h2 id = "implementation-details" > < a class = "doc-anchor" href = "#implementation-details" > §< / a > Implementation details< / h2 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< h2 id = "faq" > < a class = "doc-anchor" href = "#faq" > §< / a > F.A.Q.< / h2 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< h2 id = "related-crates" > < a class = "doc-anchor" href = "#related-crates" > §< / a > Related crates< / h2 >
2024-02-13 06:38:44 +00:00
< 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 >
2024-03-27 11:12:16 +00:00
< / 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 >