3939//! }
4040//!
4141//! // 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);
4543//! fn log(msg: &str) -> bool {
4644//! if let Some(info) = LOGGER.load(Ordering::SeqCst) {
4745//! info.logger.log(msg);
7371//! ```
7472#![ no_std]
7573
76- use core:: sync:: atomic:: { AtomicUsize , ATOMIC_USIZE_INIT , Ordering } ;
74+ use core:: sync:: atomic:: { AtomicPtr , Ordering } ;
7775use core:: marker:: PhantomData ;
7876use core:: fmt;
77+ use core:: ptr:: null_mut;
7978use core:: default:: Default ;
8079
8180/// A mutable Option<&'a, T> type which can be safely shared between threads.
8281#[ repr( C ) ]
8382pub struct AtomicRef < ' a , T : ' a > {
84- data : AtomicUsize ,
83+ data : AtomicPtr < T > ,
8584 // Make `AtomicRef` invariant over `'a` and `T`
86- _marker : PhantomData < & ' a mut & ' a mut T > ,
85+ _marker : PhantomData < Invariant < ' a , T > > ,
8786}
8887
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 ) ;
11291
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 {
17795 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 ( ) ,
18098 }
18199}
182100
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
184102/// `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 ( )
187105}
188106
189107impl < ' a , T > AtomicRef < ' a , T > {
@@ -197,9 +115,9 @@ impl<'a, T> AtomicRef<'a, T> {
197115 /// static VALUE: i32 = 10;
198116 /// let atomic_ref = AtomicRef::new(Some(&VALUE));
199117 /// ```
200- pub fn new ( p : Option < & ' a T > ) -> AtomicRef < ' a , T > {
118+ pub const fn new ( p : Option < & ' a T > ) -> AtomicRef < ' a , T > {
201119 AtomicRef {
202- data : AtomicUsize :: new ( from_opt ( p) ) ,
120+ data : AtomicPtr :: new ( from_opt ( p) ) ,
203121 _marker : PhantomData ,
204122 }
205123 }
@@ -410,10 +328,9 @@ impl<'a, T> Default for AtomicRef<'a, T> {
410328#[ cfg( test) ]
411329mod tests {
412330 use core:: sync:: atomic:: Ordering ;
331+ use super :: AtomicRef ;
413332
414- static_atomic_ref ! {
415- static FOO : AtomicRef <i32 >;
416- }
333+ static FOO : AtomicRef < i32 > = AtomicRef :: new ( None ) ;
417334
418335 static A : i32 = 10 ;
419336
0 commit comments