/rust/registry/src/index.crates.io-1949cf8c6b5b557f/conquer-once-0.3.2/src/spin.rs
Line | Count | Source |
1 | | //! Synchronized one-time and lazy initialization primitives that use spin-locks |
2 | | //! in case of concurrent accesses under contention. |
3 | | |
4 | | use core::sync::atomic::{spin_loop_hint, Ordering}; |
5 | | |
6 | | use crate::cell::{Block, Unblock}; |
7 | | use crate::state::{AtomicOnceState, BlockedState, OnceState::WouldBlock}; |
8 | | use crate::POISON_PANIC_MSG; |
9 | | |
10 | | use self::internal::Spin; |
11 | | |
12 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
13 | | // Lazy (type alias) |
14 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
15 | | |
16 | | /// A type for lazy initialization of e.g. global static variables, which |
17 | | /// provides the same functionality as the `lazy_static!` macro. |
18 | | /// |
19 | | /// This type uses spin-locks if the initialization is contended and is thus |
20 | | /// `#[no_std]` compatible. |
21 | | /// |
22 | | /// For the API of this type alias, see the API of the generic |
23 | | /// [`Lazy`](crate::doc::Lazy) type. |
24 | | pub type Lazy<T, F = fn() -> T> = crate::lazy::Lazy<T, Spin, F>; |
25 | | |
26 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
27 | | // OnceCell (type alias) |
28 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
29 | | |
30 | | /// An interior mutability cell type which allows synchronized one-time |
31 | | /// initialization and read-only access exclusively after initialization. |
32 | | /// |
33 | | /// This type uses spin-locks if the initialization is contended and is thus |
34 | | /// `#[no_std]` compatible. |
35 | | /// |
36 | | /// For the API of this type alias, see the generic |
37 | | /// [`OnceCell`](crate::doc::OnceCell) type. |
38 | | pub type OnceCell<T> = crate::cell::OnceCell<T, Spin>; |
39 | | |
40 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
41 | | // Once (type alias) |
42 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
43 | | |
44 | | /// A synchronization primitive which can be used to run a one-time global |
45 | | /// initialization. |
46 | | /// |
47 | | /// This type uses spin-locks if the initialization is contended and is thus |
48 | | /// `#[no_std]` compatible. |
49 | | /// |
50 | | /// For the API of this type alias, see the generic |
51 | | /// [`OnceCell`](crate::doc::OnceCell) type. |
52 | | /// This is a specialization with `T = ()`. |
53 | | pub type Once = OnceCell<()>; |
54 | | |
55 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
56 | | // Spin |
57 | | //////////////////////////////////////////////////////////////////////////////////////////////////// |
58 | | |
59 | | mod internal { |
60 | | /// Blocking strategy for blocking threads using spin-locks. |
61 | | #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] |
62 | | pub struct Spin; |
63 | | } |
64 | | |
65 | | /********** impl Unblock **************************************************************************/ |
66 | | |
67 | | unsafe impl Unblock for Spin { |
68 | | #[inline(always)] |
69 | 0 | unsafe fn on_unblock(_: BlockedState) {} |
70 | | } |
71 | | |
72 | | /********** impl Block ****************************************************************************/ |
73 | | |
74 | | unsafe impl Block for Spin { |
75 | | /// Spins until the [`OnceCell`] state is set to `READY`, or panics if it |
76 | | /// becomes poisoned. |
77 | | #[inline] |
78 | | fn block(state: &AtomicOnceState) { |
79 | | // (spin:1) this acquire load syncs-with the acq-rel swap (guard:2) |
80 | | while let WouldBlock(_) = state.load(Ordering::Acquire).expect(POISON_PANIC_MSG) { |
81 | | spin_loop_hint() |
82 | | } |
83 | | } |
84 | | } |
85 | | |
86 | | #[cfg(test)] |
87 | | mod tests { |
88 | | generate_tests_non_blocking!(); |
89 | | generate_tests!(); |
90 | | } |