1- #[ cfg( not( feature = "threading" ) ) ]
1+ #[ cfg( feature = "threading" ) ]
2+ mod threading {
3+ use crate :: lock:: OnceCell ;
4+
5+ pub struct StaticCell < T : ' static > {
6+ inner : OnceCell < T > ,
7+ }
8+
9+ impl < T > StaticCell < T > {
10+ #[ doc( hidden) ]
11+ pub const fn _from_once_cell ( inner : OnceCell < T > ) -> Self {
12+ Self { inner }
13+ }
14+
15+ pub fn get ( & ' static self ) -> Option < & ' static T > {
16+ self . inner . get ( )
17+ }
18+
19+ pub fn set ( & ' static self , value : T ) -> Result < ( ) , T > {
20+ self . inner . set ( value)
21+ }
22+
23+ pub fn get_or_init < F > ( & ' static self , f : F ) -> & ' static T
24+ where
25+ F : FnOnce ( ) -> T ,
26+ {
27+ self . inner . get_or_init ( f)
28+ }
29+
30+ pub fn get_or_try_init < F , E > ( & ' static self , f : F ) -> Result < & ' static T , E >
31+ where
32+ F : FnOnce ( ) -> Result < T , E > ,
33+ {
34+ self . inner . get_or_try_init ( f)
35+ }
36+ }
37+
38+ #[ macro_export]
39+ macro_rules! static_cell {
40+ ( $( $( #[ $attr: meta] ) * $vis: vis static $name: ident: $t: ty; ) +) => {
41+ $( $( #[ $attr] ) *
42+ $vis static $name: $crate:: static_cell:: StaticCell <$t> =
43+ $crate:: static_cell:: StaticCell :: _from_once_cell( $crate:: lock:: OnceCell :: new( ) ) ; ) +
44+ } ;
45+ }
46+ }
47+ #[ cfg( feature = "threading" ) ]
48+ pub use threading:: * ;
49+
50+ #[ cfg( all( not( feature = "threading" ) , feature = "std" ) ) ]
251mod non_threading {
352 use crate :: lock:: OnceCell ;
453 use std:: thread:: LocalKey ;
@@ -22,12 +71,10 @@ mod non_threading {
2271 }
2372
2473 pub fn set ( & ' static self , value : T ) -> Result < ( ) , T > {
25- // thread-safe because it's a unsync::OnceCell
2674 self . inner . with ( |x| {
2775 if x. get ( ) . is_some ( ) {
2876 Err ( value)
2977 } else {
30- // will never fail
3178 let _ = x. set ( leak ( value) ) ;
3279 Ok ( ( ) )
3380 }
@@ -65,43 +112,51 @@ mod non_threading {
65112 } ;
66113 }
67114}
68- #[ cfg( not( feature = "threading" ) ) ]
115+ #[ cfg( all ( not( feature = "threading" ) , feature = "std ") ) ]
69116pub use non_threading:: * ;
70117
71- #[ cfg( feature = "threading" ) ]
72- mod threading {
118+ // Same as `threading` variant, but wraps unsync::OnceCell with Sync.
119+ #[ cfg( all( not( feature = "threading" ) , not( feature = "std" ) ) ) ]
120+ mod no_std {
73121 use crate :: lock:: OnceCell ;
74122
123+ // unsync::OnceCell is !Sync, but without std there can be no threads.
124+ struct SyncOnceCell < T > ( OnceCell < T > ) ;
125+ // SAFETY: Without std, threading is impossible.
126+ unsafe impl < T > Sync for SyncOnceCell < T > { }
127+
75128 pub struct StaticCell < T : ' static > {
76- inner : OnceCell < T > ,
129+ inner : SyncOnceCell < T > ,
77130 }
78131
79132 impl < T > StaticCell < T > {
80133 #[ doc( hidden) ]
81134 pub const fn _from_once_cell ( inner : OnceCell < T > ) -> Self {
82- Self { inner }
135+ Self {
136+ inner : SyncOnceCell ( inner) ,
137+ }
83138 }
84139
85140 pub fn get ( & ' static self ) -> Option < & ' static T > {
86- self . inner . get ( )
141+ self . inner . 0 . get ( )
87142 }
88143
89144 pub fn set ( & ' static self , value : T ) -> Result < ( ) , T > {
90- self . inner . set ( value)
145+ self . inner . 0 . set ( value)
91146 }
92147
93148 pub fn get_or_init < F > ( & ' static self , f : F ) -> & ' static T
94149 where
95150 F : FnOnce ( ) -> T ,
96151 {
97- self . inner . get_or_init ( f)
152+ self . inner . 0 . get_or_init ( f)
98153 }
99154
100155 pub fn get_or_try_init < F , E > ( & ' static self , f : F ) -> Result < & ' static T , E >
101156 where
102157 F : FnOnce ( ) -> Result < T , E > ,
103158 {
104- self . inner . get_or_try_init ( f)
159+ self . inner . 0 . get_or_try_init ( f)
105160 }
106161 }
107162
@@ -114,5 +169,5 @@ mod threading {
114169 } ;
115170 }
116171}
117- #[ cfg( feature = "threading" ) ]
118- pub use threading :: * ;
172+ #[ cfg( all ( not ( feature = "threading" ) , not ( feature = "std" ) ) ) ]
173+ pub use no_std :: * ;
0 commit comments