rt/rust/src/sync/once.rs

49 lines
1.0 KiB
Rust

use core::sync::atomic::{AtomicI32, Ordering};
use crate::sync::Mutex;
pub struct Once {
done: AtomicI32,
mutex: Mutex<()>,
}
impl Once {
pub const fn init(once: &'static Once) -> Once {
Once {
done: AtomicI32::new(0),
mutex: Mutex::init(&once.mutex, ()),
}
}
pub fn call_once<F: FnOnce()>(&self, f: F) {
if self.done.load(Ordering::Acquire) == 0 {
let _guard = self.mutex.lock();
if self.done.load(Ordering::Relaxed) == 0 {
f();
self.done.store(1, Ordering::Release);
}
}
}
pub fn is_completed(&self) -> bool {
self.done.load(Ordering::Acquire) != 0
}
}
#[macro_export]
macro_rules! once {
($name: ident) => {
static $name: $crate::sync::Once = $crate::sync::Once::init(&$name);
};
}
#[cfg(test)]
mod tests {
#[test]
fn fast_path() {
once!(ONCE);
ONCE.call_once(|| {});
assert!(ONCE.is_completed());
}
}