pub struct Once {/* private fields */ }Expand description
A low-level synchronization primitive for one-time global execution.
Previously this was the only “execute once” synchronization instd.Other libraries implemented novel synchronizing types withOnce, likeOnceLock<T> orLazyLock<T, F>, before those were added tostd.OnceLock<T> in particular supersedesOnce in functionality and shouldbe preferred for the common case where theOnce is associated with data.
This type can only be constructed withOnce::new().
§Examples
Implementations§
Source§implOnce
implOnce
1.0.0 ·Sourcepub fncall_once<F>(&self, f: F)where F:FnOnce(),
pub fncall_once<F>(&self, f: F)where F:FnOnce(),
Performs an initialization routine once and only once. The given closurewill be executed if this is the first timecall_once has been called,and otherwise the routine willnot be invoked.
This method will block the calling thread if another initializationroutine is currently running.
When this function returns, it is guaranteed that some initializationhas run and completed (it might not be the closure specified). It is alsoguaranteed that any memory writes performed by the executed closure canbe reliably observed by other threads at this point (there is ahappens-before relation between the closure and code executing after thereturn).
If the given closure recursively invokescall_once on the sameOnceinstance, the exact behavior is not specified: allowed outcomes area panic or a deadlock.
§Examples
usestd::sync::Once;staticmutVAL: usize =0;staticINIT: Once = Once::new();// Accessing a `static mut` is unsafe much of the time, but if we do so// in a synchronized fashion (e.g., write once or read all) then we're// good to go!//// This function will only call `expensive_computation` once, and will// otherwise always return the value returned from the first invocation.fnget_cached_val() -> usize {unsafe{ INIT.call_once(|| { VAL = expensive_computation(); }); VAL }}fnexpensive_computation() -> usize {// ...}§Panics
The closuref will only be executed once even if this is calledconcurrently amongst many threads. If that closure panics, however, thenit willpoison thisOnce instance, causing all future invocations ofcall_once to also panic.
This is similar topoisoning with mutexes, but this mechanismis guaranteed to never skip panics withinf.
1.51.0 ·Sourcepub fncall_once_force<F>(&self, f: F)
pub fncall_once_force<F>(&self, f: F)
Performs the same function ascall_once() except ignores poisoning.
Unlikecall_once(), if thisOnce has been poisoned (i.e., a previouscall tocall_once() orcall_once_force() caused a panic), callingcall_once_force() will still invoke the closuref and willnotresult in an immediate panic. Iff panics, theOnce will remainin a poison state. Iff doesnot panic, theOnce will nolonger be in a poison state and all future calls tocall_once() orcall_once_force() will be no-ops.
The closuref is yielded aOnceState structure which can be usedto query the poison status of theOnce.
§Examples
usestd::sync::Once;usestd::thread;staticINIT: Once = Once::new();// poison the oncelethandle = thread::spawn(|| { INIT.call_once(||panic!());});assert!(handle.join().is_err());// poisoning propagateslethandle = thread::spawn(|| { INIT.call_once(|| {});});assert!(handle.join().is_err());// call_once_force will still run and reset the poisoned stateINIT.call_once_force(|state| {assert!(state.is_poisoned());});// once any success happens, we stop propagating the poisonINIT.call_once(|| {});1.43.0 ·Sourcepub fnis_completed(&self) ->bool
pub fnis_completed(&self) ->bool
Returnstrue if somecall_once() call has completedsuccessfully. Specifically,is_completed will return false inthe following situations:
call_once()was not called at all,call_once()was called, but has not yet completed,- the
Onceinstance is poisoned
This function returningfalse does not mean thatOnce has not beenexecuted. For example, it may have been executed in the time betweenwhenis_completed starts executing and when it returns, in which casethefalse return value would be stale (but still permissible).
§Examples
1.86.0 ·Sourcepub fnwait(&self)
pub fnwait(&self)
Blocks the current thread until initialization has completed.
§Example
usestd::sync::Once;usestd::thread;staticREADY: Once = Once::new();letthread = thread::spawn(|| { READY.wait();println!("everything is ready");});READY.call_once(||println!("performing setup"));§Panics
If thisOnce has been poisoned because an initialization closure haspanicked, this method will also panic. Usewait_forceif this behavior is not desired.
1.86.0 ·Sourcepub fnwait_force(&self)
pub fnwait_force(&self)
Blocks the current thread until initialization has completed, ignoringpoisoning.
If thisOnce has been poisoned, this function blocks until itbecomes completed, unlikeOnce::wait(), which panics in this case.