39
39
//! }
40
40
//!
41
41
//! // The methods for working with our currently defined static logger
42
- //! static_atomic_ref! {
43
- //! static LOGGER: AtomicRef<LoggerInfo>;
44
- //! }
42
+ //! static LOGGER: AtomicRef<LoggerInfo> = AtomicRef::new(None);
45
43
//! fn log(msg: &str) -> bool {
46
44
//! if let Some(info) = LOGGER.load(Ordering::SeqCst) {
47
45
//! info.logger.log(msg);
73
71
//! ```
74
72
#![ no_std]
75
73
76
- use core:: sync:: atomic:: { AtomicUsize , ATOMIC_USIZE_INIT , Ordering } ;
74
+ use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
77
75
use core:: marker:: PhantomData ;
78
76
use core:: fmt;
77
+ use core:: ptr:: null_mut;
79
78
use core:: default:: Default ;
80
79
81
80
/// A mutable Option<&'a, T> type which can be safely shared between threads.
82
81
#[ repr( C ) ]
83
82
pub struct AtomicRef < ' a , T : ' a > {
84
- data : AtomicUsize ,
83
+ data : AtomicPtr < T > ,
85
84
// Make `AtomicRef` invariant over `'a` and `T`
86
- _marker : PhantomData < & ' a mut & ' a mut T > ,
85
+ _marker : PhantomData < Invariant < ' a , T > > ,
87
86
}
88
87
89
- /// You will probably never need to use this type. It exists mostly for internal
90
- /// use in the `static_atomic_ref!` macro.
91
- ///
92
- /// Unlike `AtomicUsize` and its ilk, we cannot have an `ATOMIC_REF_INIT` const
93
- /// which is initialized to `None`, as constants cannot be generic over a type
94
- /// parameter. This is the same reason why `AtomicPtr` does not have an
95
- /// `ATOMIC_PTR_INIT` const.
96
- ///
97
- /// Instead, we have a single const for `&'static u8`, and take advantage of the
98
- /// fact that all AtomicRef types have identical layout to implement the
99
- /// `static_atomic_ref!` macro.
100
- ///
101
- /// Please use `static_atomic_ref!` instead of this constant if you need to
102
- /// implement a static atomic reference variable.
103
- pub const ATOMIC_U8_REF_INIT : AtomicRef < ' static , u8 > = AtomicRef {
104
- data : ATOMIC_USIZE_INIT ,
105
- _marker : PhantomData ,
106
- } ;
107
-
108
- /// Re-export `core` for `static_atomic_ref!` (which may be used in a
109
- /// non-`no_std` crate, where `core` is unavailable).
110
- #[ doc( hidden) ]
111
- pub use core:: { mem as core_mem, ops as core_ops} ;
88
+ // Work-around for the construction of `PhantomData<&mut _>` requiring
89
+ // `#![feature(const_fn)]`
90
+ struct Invariant < ' a , T : ' a > ( & ' a mut & ' a mut T ) ;
112
91
113
- /// A macro to define a statically allocated `AtomicRef<'static, T>` which is
114
- /// initialized to `None`.
115
- ///
116
- /// # Examples
117
- ///
118
- /// ```
119
- /// # #[macro_use]
120
- /// # extern crate atomic_ref;
121
- /// use std::sync::atomic::Ordering;
122
- ///
123
- /// static_atomic_ref! {
124
- /// static SOME_REFERENCE: AtomicRef<i32>;
125
- /// pub static PUB_REFERENCE: AtomicRef<u64>;
126
- /// }
127
- ///
128
- /// fn main() {
129
- /// let a: Option<&'static i32> = SOME_REFERENCE.load(Ordering::SeqCst);
130
- /// assert_eq!(a, None);
131
- /// }
132
- /// ```
133
- #[ macro_export]
134
- macro_rules! static_atomic_ref {
135
- ( $( #[ $attr: meta] ) * static $N: ident : AtomicRef <$T: ty>; $( $t: tt) * ) => {
136
- static_atomic_ref!( @PRIV , $( #[ $attr] ) * static $N : $T; $( $t) * ) ;
137
- } ;
138
- ( $( #[ $attr: meta] ) * pub static $N: ident : AtomicRef <$T: ty>; $( $t: tt) * ) => {
139
- static_atomic_ref!( @PUB , $( #[ $attr] ) * static $N : $T; $( $t) * ) ;
140
- } ;
141
- ( @$VIS: ident, $( #[ $attr: meta] ) * static $N: ident : $T: ty; $( $t: tt) * ) => {
142
- static_atomic_ref!( @MAKE TY , $VIS, $( #[ $attr] ) * , $N) ;
143
- impl $crate:: core_ops:: Deref for $N {
144
- type Target = $crate:: AtomicRef <' static , $T>;
145
- #[ allow( unsafe_code) ]
146
- fn deref<' a>( & ' a self ) -> & ' a $crate:: AtomicRef <' static , $T> {
147
- static STORAGE : $crate:: AtomicRef <' static , u8 > = $crate:: ATOMIC_U8_REF_INIT ;
148
- unsafe { $crate:: core_mem:: transmute( & STORAGE ) }
149
- }
150
- }
151
- static_atomic_ref!( $( $t) * ) ;
152
- } ;
153
- ( @MAKE TY , PUB , $( #[ $attr: meta] ) * , $N: ident) => {
154
- #[ allow( missing_copy_implementations) ]
155
- #[ allow( non_camel_case_types) ]
156
- #[ allow( dead_code) ]
157
- $( #[ $attr] ) *
158
- pub struct $N { _private: ( ) }
159
- #[ doc( hidden) ]
160
- pub static $N: $N = $N { _private: ( ) } ;
161
- } ;
162
- ( @MAKE TY , PRIV , $( #[ $attr: meta] ) * , $N: ident) => {
163
- #[ allow( missing_copy_implementations) ]
164
- #[ allow( non_camel_case_types) ]
165
- #[ allow( dead_code) ]
166
- $( #[ $attr] ) *
167
- struct $N { _private: ( ) }
168
- #[ doc( hidden) ]
169
- static $N: $N = $N { _private: ( ) } ;
170
- } ;
171
- ( ) => ( ) ;
172
- }
173
-
174
- /// An internal helper function for converting `Option<&'a T>` values to usize
175
- /// for storing in the `AtomicUsize`.
176
- fn from_opt < ' a , T > ( p : Option < & ' a T > ) -> usize {
92
+ /// An internal helper function for converting `Option<&'a T>` values to
93
+ /// `*mut T` for storing in the `AtomicUsize`.
94
+ const fn from_opt < ' a , T > ( p : Option < & ' a T > ) -> * mut T {
177
95
match p {
178
- Some ( p) => p as * const T as usize ,
179
- None => 0 ,
96
+ Some ( p) => p as * const T as * mut T ,
97
+ None => null_mut ( ) ,
180
98
}
181
99
}
182
100
183
- /// An internal helper function for converting `usize ` values stored in the
101
+ /// An internal helper function for converting `*mut T ` values stored in the
184
102
/// `AtomicUsize` back into `Option<&'a T>` values.
185
- unsafe fn to_opt < ' a , T > ( p : usize ) -> Option < & ' a T > {
186
- ( p as * const T ) . as_ref ( )
103
+ unsafe fn to_opt < ' a , T > ( p : * mut T ) -> Option < & ' a T > {
104
+ p . as_ref ( )
187
105
}
188
106
189
107
impl < ' a , T > AtomicRef < ' a , T > {
@@ -197,9 +115,9 @@ impl<'a, T> AtomicRef<'a, T> {
197
115
/// static VALUE: i32 = 10;
198
116
/// let atomic_ref = AtomicRef::new(Some(&VALUE));
199
117
/// ```
200
- pub fn new ( p : Option < & ' a T > ) -> AtomicRef < ' a , T > {
118
+ pub const fn new ( p : Option < & ' a T > ) -> AtomicRef < ' a , T > {
201
119
AtomicRef {
202
- data : AtomicUsize :: new ( from_opt ( p) ) ,
120
+ data : AtomicPtr :: new ( from_opt ( p) ) ,
203
121
_marker : PhantomData ,
204
122
}
205
123
}
@@ -410,10 +328,9 @@ impl<'a, T> Default for AtomicRef<'a, T> {
410
328
#[ cfg( test) ]
411
329
mod tests {
412
330
use core:: sync:: atomic:: Ordering ;
331
+ use super :: AtomicRef ;
413
332
414
- static_atomic_ref ! {
415
- static FOO : AtomicRef <i32 >;
416
- }
333
+ static FOO : AtomicRef < i32 > = AtomicRef :: new ( None ) ;
417
334
418
335
static A : i32 = 10 ;
419
336
0 commit comments