static_init/
raw_static.rs1pub use static_impl::{ConstStatic, Static, __set_init_prio};
2
3#[cfg(debug_mode)]
4mod static_impl {
5
6 use crate::{FinalyMode, InitMode, StaticInfo};
7
8 use core::cmp::Ordering::*;
9 use core::mem::MaybeUninit;
10 use core::ops::{Deref, DerefMut};
11 use core::sync::atomic::{AtomicI32, Ordering};
12
13 pub struct Static<T>(MaybeUninit<T>, StaticInfo, AtomicI32);
20
21 pub struct ConstStatic<T>(Static<T>);
28
29 static CUR_INIT_PRIO: AtomicI32 = AtomicI32::new(i32::MIN);
30
31 static CUR_DROP_PRIO: AtomicI32 = AtomicI32::new(i32::MIN);
32
33 #[doc(hidden)]
34 #[inline]
35 pub fn __set_init_prio(v: i32) {
36 CUR_INIT_PRIO.store(v, Ordering::Relaxed);
37 }
38
39 impl<T> Static<T> {
40 #[inline]
41 pub const unsafe fn uninit(info: StaticInfo) -> Self {
48 Self(MaybeUninit::uninit(), info, AtomicI32::new(0))
49 }
50 #[inline]
51 pub const fn from(v: T, info: StaticInfo) -> Self {
52 Static(MaybeUninit::new(v), info, AtomicI32::new(1))
53 }
54
55 #[inline]
56 pub fn set_to(this: &'static mut Self, v: T) {
57 this.0 = MaybeUninit::new(v);
58 this.2.store(1, Ordering::Relaxed);
59 }
60
61 #[inline]
62 pub unsafe fn drop(this: &'static mut Self) {
66 if let FinalyMode::ProgramDestructor(prio) = &this.1.drop_mode {
67 CUR_DROP_PRIO.store(*prio as i32, Ordering::Relaxed);
68 this.0.as_mut_ptr().drop_in_place();
69 CUR_DROP_PRIO.store(i32::MIN, Ordering::Relaxed);
70 } else {
71 this.0.as_mut_ptr().drop_in_place();
72 };
73 this.2.store(2, Ordering::Relaxed);
74 }
75 }
76
77 #[inline]
78 fn check_access(info: &StaticInfo, status: i32) {
79 if status == 0 {
80 core::panic!(
81 "Attempt to access variable {:#?} before it is initialized during initialization \
82 priority {}. Tip: increase init priority of this static to a value larger than \
83 {prio} (attribute syntax: `#[dynamic(init=<prio>)]`)",
84 info,
85 prio = CUR_INIT_PRIO.load(Ordering::Relaxed)
86 )
87 }
88 if status == 2 {
89 core::panic!(
90 "Attempt to access variable {:#?} after it was destroyed during destruction \
91 priority {prio}. Tip increase drop priority of this static to a value larger \
92 than {prio} (attribute syntax: `#[dynamic(drop=<prio>)]`)",
93 info,
94 prio = CUR_DROP_PRIO.load(Ordering::Relaxed)
95 )
96 }
97 let init_prio = CUR_INIT_PRIO.load(Ordering::Relaxed);
98 let drop_prio = CUR_DROP_PRIO.load(Ordering::Relaxed);
99
100 if let FinalyMode::ProgramDestructor(prio) = &info.drop_mode {
101 match drop_prio.cmp(&(*prio as i32)) {
102 Equal => core::panic!(
103 "This access to variable {:#?} is not sequenced before to its drop. Tip \
104 increase drop priority of this static to a value larger than {prio} \
105 (attribute syntax: `#[dynamic(drop=<prio>)]`)",
106 info,
107 prio = drop_prio
108 ),
109 Greater => core::panic!(
110 "Unexpected initialization order while accessing {:#?} from drop priority {}. \
111 This is a bug of `static_init` library, please report \"
112 the issue inside `static_init` repository.",
113 info,
114 drop_prio
115 ),
116 Less => (),
117 }
118 }
119
120 if let InitMode::ProgramConstructor(prio) = &info.init_mode {
121 match init_prio.cmp(&(*prio as i32)) {
122 Equal => core::panic!(
123 "This access to variable {:#?} is not sequenced after construction of this \
124 static. Tip increase init priority of this static to a value larger than \
125 {prio} (attribute syntax: `#[dynamic(init=<prio>)]`)",
126 info,
127 prio = init_prio
128 ),
129 Greater => core::panic!(
130 "Unexpected initialization order while accessing {:#?} from init priority {}. \
131 This is a bug of `static_init` library, please report \"
132 the issue inside `static_init` repository.",
133 info,
134 init_prio,
135 ),
136 Less => (),
137 }
138 }
139 }
140
141 impl<T> Deref for Static<T> {
142 type Target = T;
143 #[inline(always)]
144 fn deref(&self) -> &T {
145 check_access(&self.1, self.2.load(Ordering::Relaxed));
146 unsafe { &*self.0.as_ptr() }
151 }
152 }
153 impl<T> DerefMut for Static<T> {
154 #[inline(always)]
155 fn deref_mut(&mut self) -> &mut T {
156 check_access(&self.1, self.2.load(Ordering::Relaxed));
157 unsafe { &mut *self.0.as_mut_ptr() }
162 }
163 }
164
165 impl<T> ConstStatic<T> {
166 #[inline]
167 pub const unsafe fn uninit(info: StaticInfo) -> Self {
174 Self(Static::uninit(info))
175 }
176 #[inline]
177 pub const fn from(v: T, info: StaticInfo) -> Self {
178 Self(Static::from(v, info))
179 }
180 #[inline]
181 pub fn set_to(this: &'static mut Self, v: T) {
185 Static::set_to(&mut this.0, v)
186 }
187 #[inline]
188 pub unsafe fn drop(this: &'static mut Self) {
192 Static::drop(&mut this.0);
193 }
194 }
195
196 impl<T> Deref for ConstStatic<T> {
197 type Target = T;
198 #[inline(always)]
199 fn deref(&self) -> &T {
200 &*self.0
205 }
206 }
207}
208
209#[cfg(not(debug_mode))]
210mod static_impl {
211 use core::mem::MaybeUninit;
212 use core::ops::{Deref, DerefMut};
213
214 pub struct Static<T>(MaybeUninit<T>);
221
222 pub struct ConstStatic<T>(Static<T>);
229
230 #[doc(hidden)]
231 #[inline(always)]
232 pub fn __set_init_prio(_: i32) {}
233
234 impl<T> Static<T> {
236 #[inline]
237 pub const unsafe fn uninit() -> Self {
243 Self(MaybeUninit::uninit())
244 }
245 #[inline]
246 pub const fn from(v: T) -> Self {
247 Self(MaybeUninit::new(v))
248 }
249
250 #[inline]
251 pub fn set_to(this: &'static mut Self, v: T) {
252 this.0 = MaybeUninit::new(v);
253 }
254
255 #[inline]
256 pub unsafe fn drop(this: &'static mut Self) {
262 this.0.as_mut_ptr().drop_in_place();
263 }
264 }
265
266 impl<T> Deref for Static<T> {
267 type Target = T;
268 #[inline(always)]
269 fn deref(&self) -> &T {
270 unsafe { &*self.0.as_ptr() }
275 }
276 }
277 impl<T> DerefMut for Static<T> {
278 #[inline(always)]
279 fn deref_mut(&mut self) -> &mut T {
280 unsafe { &mut *self.0.as_mut_ptr() }
285 }
286 }
287
288 impl<T> ConstStatic<T> {
289 #[inline]
290 pub const unsafe fn uninit() -> Self {
296 Self(Static::uninit())
297 }
298 #[inline]
299 pub const fn from(v: T) -> Self {
300 Self(Static::from(v))
301 }
302 #[inline]
303 pub fn set_to(this: &'static mut Self, v: T) {
304 Static::set_to(&mut this.0, v)
305 }
306 #[inline]
307 pub unsafe fn drop(this: &'static mut Self) {
311 Static::drop(&mut this.0);
312 }
313 }
314
315 impl<T> Deref for ConstStatic<T> {
316 type Target = T;
317 #[inline(always)]
318 fn deref(&self) -> &T {
319 &*self.0
324 }
325 }
326}