cluStaticData/once_const_static/core/
atomic_lock.rs1
2use core::sync::atomic::AtomicU8;
3use core::sync::atomic::Ordering;
4use core::cell::UnsafeCell;
5
6use crate::once_const_static::generic::UnsafeGenericStaticData;
7use crate::once_const_static::generic::GenericStaticData;
8use crate::once_const_static::UnkStaticData;
9
10use crate::err::IgnoreInitErr;
11use crate::err::StaticErr;
12
13
14const UNINITIALIZED: u8 = 0;
15const INITIALIZING: u8 = 1;
18const INITIALIZED: u8 = 2;
21impl<T> UnkStaticData<T, AtomicU8> {
25 #[inline]
26 pub const fn new(a: T) -> Self {
27 Self {
28 data: UnsafeCell::new(a),
29 sync_data: AtomicU8::new(UNINITIALIZED),
30 }
31 }
32
33 #[inline]
34 fn lock_logic<B: AtomicGenErr<VT, R>, A: FnOnce(VT) -> R, R, VT>(&self, v: VT, a: A) -> R {
35 match self.sync_data.compare_and_swap(UNINITIALIZED, INITIALIZING, Ordering::SeqCst) {
36 UNINITIALIZED => {
37 let result = a(v);
39 self.sync_data.store(INITIALIZED, Ordering::SeqCst);
40
41 result
42 },
43 INITIALIZING => {
44 while self.sync_data.load(Ordering::SeqCst) == INITIALIZING {}
46 B::create_err(v)
47 },
48 _ => {
49 B::create_err(v)
50 },
51 }
53 }
54
55 #[inline]
56 fn ignore_initialize_logic<B: AtomicGenErr<(), R>, A: FnOnce() -> R, R>(&self, a: A) -> R {
57 match self.sync_data.compare_and_swap(UNINITIALIZED, INITIALIZING, Ordering::SeqCst) {
58 UNINITIALIZED => {
59 let result = a();
61 self.sync_data.store(INITIALIZED, Ordering::SeqCst);
62
63 result
64 },
65 INITIALIZING => {
66 while self.sync_data.load(Ordering::SeqCst) == INITIALIZING {}
68 B::create_err(())
69 },
70 _ => B::create_err(()),
71 }
73 }
74
75 #[inline]
76 fn is_init_state_logic(&self) -> bool {
77 match self.sync_data.load(Ordering::SeqCst) {
78 UNINITIALIZED => false,
79 _ => true,
82 }
83 }
84
85 #[inline]
86 fn raw_ignore_initialize_logic(&self) {
87 let _e = self.sync_data.compare_and_swap(UNINITIALIZED, INITIALIZING, Ordering::SeqCst);
89 }
90}
91
92
93impl<T> UnsafeGenericStaticData<T> for UnkStaticData<&'static T, AtomicU8> where T: 'static {
94 unsafe fn set_box(&self, v: Box<T>) -> Result<(), StaticErr<Box<T>>> {
95 self.lock_logic::<StaticErrPrev, _, _, _>(v, |v| {
96 #[allow(unused_unsafe)]
97 unsafe {
98 *self.data.get() = &*Box::into_raw(v);
99 }
100 Ok( () )
101 })
102 }
103
104 unsafe fn set_raw(&self, v: T) -> Result<(), StaticErr<T>> {
105 self.lock_logic::<StaticErrPrev, _, _, _>(v, |v| {
106 let v = Box::new(v);
107
108 #[allow(unused_unsafe)]
109 unsafe {
110 *self.data.get() = &*Box::into_raw(v);
111 }
112 Ok( () )
113 })
114 }
115}
116
117impl<T> GenericStaticData<T> for UnkStaticData<T, AtomicU8> {
118 fn set(&self, v: T) -> Result<(), StaticErr<T>> {
119 self.lock_logic::<StaticErrPrev, _, _, _>(v,
120 |v| { unsafe { *self.data.get() = v; } Ok( () )},
121 )
123 }
124
125 fn replace(&self, v: T) -> Result<T, StaticErr<T>> {
126 self.lock_logic::<StaticErrPrev, _, _, _>(v,
127 |v| Ok( std::mem::replace(unsafe { &mut *self.data.get() }, v) ),
128 )
131 }
132
133 unsafe fn unsafe_replace(&self, v: T) -> T {
134 #[allow(unused_unsafe)]
135 std::mem::replace(unsafe { &mut *self.data.get() }, v)
136 }
137
138 fn get<'a>(&'a self) -> &'a T {
139 unsafe{ &*self.data.get() }
140 }
141
142 fn ignore_initialize(&self) -> Result<(), IgnoreInitErr> {
143 self.ignore_initialize_logic::<IgnoreInitErrPrev, _, _>(
144 || Ok( () ),
145 )
147 }
148
149 #[inline(always)]
150 fn ignore_initialize_dont_result(&self) {
151 self.raw_ignore_initialize_logic()
152 }
153
154 #[inline(always)]
155 fn is_init_state(&self) -> bool {
156 self.is_init_state_logic()
157 }
158}
159
160
161trait AtomicGenErr<D, T> {
162 fn create_err(d: D) -> T;
163}
164
165
166enum IgnoreInitErrPrev {}
167impl<OKR, D> AtomicGenErr<D, Result<OKR, IgnoreInitErr>> for IgnoreInitErrPrev {
168 #[inline(always)]
169 fn create_err(_d: D) -> Result<OKR, IgnoreInitErr> {
170 Err(IgnoreInitErr::prev())
171 }
172}
173
174
175enum StaticErrPrev {}
176impl<OKR, D> AtomicGenErr<D, Result<OKR, StaticErr<D>>> for StaticErrPrev {
177 #[inline(always)]
178 fn create_err(d: D) -> Result<OKR, StaticErr<D>> {
179 Err(StaticErr::prev(d))
180 }
181}