1#![allow(deprecated)]
6
7use std::mem;
8use std::sync;
9
10#[deprecated(
12 since = "2.16",
13 note = "Please regenerate .rs files from .proto files to use newer APIs"
14)]
15pub struct Lazy<T> {
16 #[doc(hidden)]
17 pub lock: sync::Once,
18 #[doc(hidden)]
19 pub ptr: *const T,
20}
21
22impl<T> Lazy<T> {
23 pub const INIT: Lazy<T> = Lazy {
28 lock: sync::Once::new(),
29 ptr: 0 as *const T,
30 };
31
32 pub fn get<F>(&'static mut self, init: F) -> &'static T
34 where
35 F: FnOnce() -> T,
36 {
37 let lock: &sync::Once = unsafe { mem::transmute(&self.lock) };
43 lock.call_once(|| unsafe {
44 self.ptr = mem::transmute(Box::new(init()));
45 });
46 unsafe { &*self.ptr }
47 }
48}
49
50#[deprecated(
52 since = "2.11",
53 note = "Regenerate .proto files to use safer initializer"
54)]
55pub const ONCE_INIT: sync::Once = sync::Once::new();
56
57#[cfg(test)]
58mod test {
59 use std::sync::atomic::AtomicIsize;
60 use std::sync::atomic::Ordering;
61 use std::sync::Arc;
62 use std::sync::Barrier;
63 use std::thread;
64
65 use super::Lazy;
66
67 #[test]
68 fn many_threads_calling_get() {
69 const N_THREADS: usize = 32;
70 const N_ITERS_IN_THREAD: usize = 32;
71 const N_ITERS: usize = 16;
72
73 static mut LAZY: Lazy<String> = Lazy::INIT;
74 static CALL_COUNT: AtomicIsize = AtomicIsize::new(0);
75
76 let value = "Hello, world!".to_owned();
77
78 for _ in 0..N_ITERS {
79 unsafe {
81 LAZY = Lazy::INIT;
82 }
83 CALL_COUNT.store(0, Ordering::SeqCst);
84
85 let mut threads = vec![];
87 let barrier = Arc::new(Barrier::new(N_THREADS));
88
89 for _ in 0..N_THREADS {
90 let cloned_value_thread = value.clone();
91 let cloned_barrier = barrier.clone();
92 threads.push(thread::spawn(move || {
93 cloned_barrier.wait();
95 for _ in 0..N_ITERS_IN_THREAD {
96 assert_eq!(&cloned_value_thread, unsafe {
97 LAZY.get(|| {
98 CALL_COUNT.fetch_add(1, Ordering::SeqCst);
99 cloned_value_thread.clone()
100 })
101 });
102 }
103 }));
104 }
105
106 for thread in threads {
107 thread.join().unwrap();
108 }
109
110 assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
111 }
112 }
113}