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