rustpython_common/
static_cell.rs1#[cfg(not(feature = "threading"))]
2mod non_threading {
3 use crate::lock::OnceCell;
4 use std::thread::LocalKey;
5
6 pub struct StaticCell<T: 'static> {
7 inner: &'static LocalKey<OnceCell<&'static T>>,
8 }
9
10 fn leak<T>(x: T) -> &'static T {
11 Box::leak(Box::new(x))
12 }
13
14 impl<T> StaticCell<T> {
15 #[doc(hidden)]
16 pub const fn _from_localkey(inner: &'static LocalKey<OnceCell<&'static T>>) -> Self {
17 Self { inner }
18 }
19
20 pub fn get(&'static self) -> Option<&'static T> {
21 self.inner.with(|x| x.get().copied())
22 }
23
24 pub fn set(&'static self, value: T) -> Result<(), T> {
25 self.inner.with(|x| {
27 if x.get().is_some() {
28 Err(value)
29 } else {
30 let _ = x.set(leak(value));
32 Ok(())
33 }
34 })
35 }
36
37 pub fn get_or_init<F>(&'static self, f: F) -> &'static T
38 where
39 F: FnOnce() -> T,
40 {
41 self.inner.with(|x| *x.get_or_init(|| leak(f())))
42 }
43
44 pub fn get_or_try_init<F, E>(&'static self, f: F) -> Result<&'static T, E>
45 where
46 F: FnOnce() -> Result<T, E>,
47 {
48 self.inner
49 .with(|x| x.get_or_try_init(|| f().map(leak)).copied())
50 }
51 }
52
53 #[macro_export]
54 macro_rules! static_cell {
55 ($($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty;)+) => {
56 $($(#[$attr])*
57 $vis static $name: $crate::static_cell::StaticCell<$t> = {
58 ::std::thread_local! {
59 $vis static $name: $crate::lock::OnceCell<&'static $t> = $crate::lock::OnceCell::new();
60 }
61 $crate::static_cell::StaticCell::_from_localkey(&$name)
62 };)+
63 };
64 }
65}
66#[cfg(not(feature = "threading"))]
67pub use non_threading::*;
68
69#[cfg(feature = "threading")]
70mod threading {
71 use crate::lock::OnceCell;
72
73 pub struct StaticCell<T: 'static> {
74 inner: OnceCell<T>,
75 }
76
77 impl<T> StaticCell<T> {
78 #[doc(hidden)]
79 pub const fn _from_oncecell(inner: OnceCell<T>) -> Self {
80 Self { inner }
81 }
82
83 pub fn get(&'static self) -> Option<&'static T> {
84 self.inner.get()
85 }
86
87 pub fn set(&'static self, value: T) -> Result<(), T> {
88 self.inner.set(value)
89 }
90
91 pub fn get_or_init<F>(&'static self, f: F) -> &'static T
92 where
93 F: FnOnce() -> T,
94 {
95 self.inner.get_or_init(f)
96 }
97
98 pub fn get_or_try_init<F, E>(&'static self, f: F) -> Result<&'static T, E>
99 where
100 F: FnOnce() -> Result<T, E>,
101 {
102 self.inner.get_or_try_init(f)
103 }
104 }
105
106 #[macro_export]
107 macro_rules! static_cell {
108 ($($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty;)+) => {
109 $($(#[$attr])*
110 $vis static $name: $crate::static_cell::StaticCell<$t> =
111 $crate::static_cell::StaticCell::_from_oncecell($crate::lock::OnceCell::new());)+
112 };
113 }
114}
115#[cfg(feature = "threading")]
116pub use threading::*;