73
73
//! ```
74
74
#![ no_std]
75
75
76
- use core:: sync:: atomic:: { AtomicUsize , ATOMIC_USIZE_INIT , Ordering } ;
76
+ use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
77
+ use core:: ptr:: null_mut;
77
78
use core:: marker:: PhantomData ;
78
79
use core:: fmt;
79
80
use core:: default:: Default ;
80
81
81
82
/// A mutable Option<&'a, T> type which can be safely shared between threads.
82
83
#[ repr( C ) ]
83
84
pub struct AtomicRef < ' a , T : ' a > {
84
- data : AtomicUsize ,
85
+ data : AtomicPtr < T > ,
85
86
// Make `AtomicRef` invariant over `'a` and `T`
86
87
_marker : PhantomData < & ' a mut & ' a mut T > ,
87
88
}
@@ -101,7 +102,7 @@ pub struct AtomicRef<'a, T: 'a> {
101
102
/// Please use `static_atomic_ref!` instead of this constant if you need to
102
103
/// implement a static atomic reference variable.
103
104
pub const ATOMIC_U8_REF_INIT : AtomicRef < ' static , u8 > = AtomicRef {
104
- data : ATOMIC_USIZE_INIT ,
105
+ data : AtomicPtr :: new ( null_mut ( ) ) ,
105
106
_marker : PhantomData ,
106
107
} ;
107
108
@@ -155,16 +156,16 @@ macro_rules! static_atomic_ref {
155
156
156
157
/// An internal helper function for converting `Option<&'a T>` values to usize
157
158
/// for storing in the `AtomicUsize`.
158
- fn from_opt < ' a , T > ( p : Option < & ' a T > ) -> usize {
159
+ fn from_opt < ' a , T > ( p : Option < & ' a T > ) -> * mut T {
159
160
match p {
160
- Some ( p) => p as * const T as usize ,
161
- None => 0 ,
161
+ Some ( p) => p as * const T as * mut T ,
162
+ None => null_mut ( ) ,
162
163
}
163
164
}
164
165
165
166
/// An internal helper function for converting `usize` values stored in the
166
167
/// `AtomicUsize` back into `Option<&'a T>` values.
167
- unsafe fn to_opt < ' a , T > ( p : usize ) -> Option < & ' a T > {
168
+ unsafe fn to_opt < ' a , T > ( p : * mut T ) -> Option < & ' a T > {
168
169
( p as * const T ) . as_ref ( )
169
170
}
170
171
@@ -173,7 +174,7 @@ impl<T: 'static> AtomicRef<'static, T> {
173
174
// fn" limitation, because of the `PhantomData`. Other methods of enforcing
174
175
// invariance hit the same sort of problem (`fn` isn't allowed either).
175
176
const NONE : Self = Self {
176
- data : AtomicUsize :: new ( 0 ) ,
177
+ data : AtomicPtr :: new ( null_mut ( ) ) ,
177
178
_marker : PhantomData ,
178
179
} ;
179
180
/// Returns a `AtomicRef<'static, T>` with a value of `None`.
@@ -192,6 +193,31 @@ impl<T: 'static> AtomicRef<'static, T> {
192
193
pub const fn static_none ( ) -> Self {
193
194
Self :: NONE
194
195
}
196
+
197
+ /// Returns a `AtomicRef<'static, T>` with a value of `Some(arg)`.
198
+ ///
199
+ /// This is useful as it is implemented as a `const fn`, and thus can
200
+ /// initialize an `AtomicRef` used as a `static`.
201
+ ///
202
+ /// # Examples
203
+ ///
204
+ /// ```
205
+ /// use atomic_ref::AtomicRef;
206
+ /// use std::sync::atomic::Ordering;
207
+ ///
208
+ /// static INITIAL: u64 = 123;
209
+ ///
210
+ /// pub static SOME_REFERENCE: AtomicRef<'static, u64> = AtomicRef::static_some(&INITIAL);
211
+ ///
212
+ /// assert_eq!(Some(&123), SOME_REFERENCE.load(Ordering::SeqCst));
213
+ /// ```
214
+ #[ inline]
215
+ pub const fn static_some ( init : & ' static T ) -> Self {
216
+ Self {
217
+ data : AtomicPtr :: new ( init as * const T as * mut T ) ,
218
+ ..Self :: NONE
219
+ }
220
+ }
195
221
}
196
222
197
223
impl < ' a , T > AtomicRef < ' a , T > {
@@ -207,7 +233,7 @@ impl<'a, T> AtomicRef<'a, T> {
207
233
/// ```
208
234
pub fn new ( p : Option < & ' a T > ) -> AtomicRef < ' a , T > {
209
235
AtomicRef {
210
- data : AtomicUsize :: new ( from_opt ( p) ) ,
236
+ data : AtomicPtr :: new ( from_opt ( p) ) ,
211
237
_marker : PhantomData ,
212
238
}
213
239
}
@@ -432,4 +458,14 @@ mod tests {
432
458
assert ! ( FOO . load( Ordering :: SeqCst ) == Some ( & A ) ) ;
433
459
assert ! ( FOO . load( Ordering :: SeqCst ) . unwrap( ) as * const _ == & A as * const _) ;
434
460
}
461
+
462
+ static BAR : super :: AtomicRef < ' static , i32 > = super :: AtomicRef :: static_some ( & A ) ;
463
+
464
+ #[ test]
465
+ fn static_some ( ) {
466
+ assert_eq ! ( BAR . load( Ordering :: SeqCst ) , Some ( & 10 ) ) ;
467
+ assert_eq ! ( BAR . load( Ordering :: SeqCst ) . unwrap( ) as * const _, & A as * const _) ;
468
+ BAR . store ( None , Ordering :: SeqCst ) ;
469
+ assert_eq ! ( BAR . load( Ordering :: SeqCst ) , None ) ;
470
+ }
435
471
}
0 commit comments