diff options
Diffstat (limited to 'src/lazy_v2.rs')
-rw-r--r-- | src/lazy_v2.rs | 90 |
1 files changed, 0 insertions, 90 deletions
diff --git a/src/lazy_v2.rs b/src/lazy_v2.rs deleted file mode 100644 index 6f9ac1e..0000000 --- a/src/lazy_v2.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! Lazily initialized data. -//! Used in generated code. - -use std::cell::UnsafeCell; -use std::sync; - -/// Lazily initialized data. -pub struct LazyV2<T: Sync> { - lock: sync::Once, - ptr: UnsafeCell<*const T>, -} - -unsafe impl<T: Sync> Sync for LazyV2<T> {} - -impl<T: Sync> LazyV2<T> { - /// Uninitialized `Lazy` object. - pub const INIT: LazyV2<T> = LazyV2 { - lock: sync::Once::new(), - ptr: UnsafeCell::new(0 as *const T), - }; - - /// Get lazy field value, initialize it with given function if not yet. - pub fn get<F>(&'static self, init: F) -> &'static T - where - F: FnOnce() -> T, - { - self.lock.call_once(|| unsafe { - *self.ptr.get() = Box::into_raw(Box::new(init())); - }); - unsafe { &**self.ptr.get() } - } -} - -#[cfg(test)] -mod test { - use std::sync::atomic::AtomicIsize; - use std::sync::atomic::Ordering; - use std::sync::Arc; - use std::sync::Barrier; - use std::thread; - - use super::LazyV2; - - #[test] - fn many_threads_calling_get() { - const N_THREADS: usize = 32; - const N_ITERS_IN_THREAD: usize = 32; - const N_ITERS: usize = 16; - - static mut LAZY: LazyV2<String> = LazyV2::INIT; - static CALL_COUNT: AtomicIsize = AtomicIsize::new(0); - - let value = "Hello, world!".to_owned(); - - for _ in 0..N_ITERS { - // Reset mutable state. - unsafe { - LAZY = LazyV2::INIT; - } - CALL_COUNT.store(0, Ordering::SeqCst); - - // Create a bunch of threads, all calling .get() at the same time. - let mut threads = vec![]; - let barrier = Arc::new(Barrier::new(N_THREADS)); - - for _ in 0..N_THREADS { - let cloned_value_thread = value.clone(); - let cloned_barrier = barrier.clone(); - threads.push(thread::spawn(move || { - // Ensure all threads start at once to maximise contention. - cloned_barrier.wait(); - for _ in 0..N_ITERS_IN_THREAD { - assert_eq!(&cloned_value_thread, unsafe { - LAZY.get(|| { - CALL_COUNT.fetch_add(1, Ordering::SeqCst); - cloned_value_thread.clone() - }) - }); - } - })); - } - - for thread in threads { - thread.join().unwrap(); - } - - assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1); - } - } -} |