1 use std::cell::UnsafeCell; 2 3 use crate::ffi::*; 4 use crate::context_and_sync_function; 5 6 /// A predicate used to execute a closure only once for the lifetime of an 7 /// application. 8 #[derive(Debug)] 9 pub struct Once { 10 predicate: UnsafeCell<dispatch_once_t>, 11 } 12 13 impl Once { 14 /// Creates a new `Once`. new() -> Once15 pub const fn new() -> Once { 16 Once { predicate: UnsafeCell::new(0) } 17 } 18 19 /// Executes a closure once, ensuring that no other closure has been or 20 /// will be executed by self for the lifetype of the application. 21 /// 22 /// If called simultaneously from multiple threads, waits synchronously 23 // until the work has completed. 24 #[inline(always)] call_once<F>(&'static self, work: F) where F: FnOnce()25 pub fn call_once<F>(&'static self, work: F) where F: FnOnce() { 26 #[cold] 27 #[inline(never)] 28 fn once<F>(predicate: *mut dispatch_once_t, work: F) 29 where F: FnOnce() { 30 let mut work = Some(work); 31 let (context, work) = context_and_sync_function(&mut work); 32 unsafe { 33 dispatch_once_f(predicate, context, work); 34 } 35 } 36 37 unsafe { 38 let predicate = self.predicate.get(); 39 if *predicate != !0 { 40 once(predicate, work); 41 } 42 } 43 } 44 } 45 46 unsafe impl Sync for Once { } 47 48 #[cfg(test)] 49 mod tests { 50 use super::Once; 51 52 #[test] test_once()53 fn test_once() { 54 static ONCE: Once = Once::new(); 55 let mut num = 0; 56 ONCE.call_once(|| num += 1); 57 ONCE.call_once(|| num += 1); 58 assert!(num == 1); 59 } 60 } 61