38
38
#[ macro_use]
39
39
extern crate std;
40
40
41
+ use core:: mem:: MaybeUninit ;
41
42
// Re-export some useful definitions from libcore
42
43
pub use core:: sync:: atomic:: { fence, Ordering } ;
43
44
@@ -55,7 +56,8 @@ mod ops;
55
56
/// between threads.
56
57
#[ repr( transparent) ]
57
58
pub struct Atomic < T > {
58
- v : UnsafeCell < T > ,
59
+ // The MaybeUninit is here to work around rust-lang/rust#87341.
60
+ v : UnsafeCell < MaybeUninit < T > > ,
59
61
}
60
62
61
63
// Atomic<T> is only Sync if T is Send
@@ -90,7 +92,7 @@ impl<T> Atomic<T> {
90
92
#[ inline]
91
93
pub const fn new ( v : T ) -> Atomic < T > {
92
94
Atomic {
93
- v : UnsafeCell :: new ( v ) ,
95
+ v : UnsafeCell :: new ( MaybeUninit :: new ( v ) ) ,
94
96
}
95
97
}
96
98
@@ -106,13 +108,18 @@ impl<T> Atomic<T> {
106
108
}
107
109
108
110
impl < T : Copy > Atomic < T > {
111
+ #[ inline]
112
+ fn inner_ptr ( & self ) -> * mut T {
113
+ self . v . get ( ) as * mut T
114
+ }
115
+
109
116
/// Returns a mutable reference to the underlying type.
110
117
///
111
118
/// This is safe because the mutable reference guarantees that no other threads are
112
119
/// concurrently accessing the atomic data.
113
120
#[ inline]
114
121
pub fn get_mut ( & mut self ) -> & mut T {
115
- unsafe { & mut * self . v . get ( ) }
122
+ unsafe { & mut * self . inner_ptr ( ) }
116
123
}
117
124
118
125
/// Consumes the atomic and returns the contained value.
@@ -121,7 +128,7 @@ impl<T: Copy> Atomic<T> {
121
128
/// concurrently accessing the atomic data.
122
129
#[ inline]
123
130
pub fn into_inner ( self ) -> T {
124
- self . v . into_inner ( )
131
+ unsafe { self . v . into_inner ( ) . assume_init ( ) }
125
132
}
126
133
127
134
/// Loads a value from the `Atomic`.
@@ -134,7 +141,7 @@ impl<T: Copy> Atomic<T> {
134
141
/// Panics if `order` is `Release` or `AcqRel`.
135
142
#[ inline]
136
143
pub fn load ( & self , order : Ordering ) -> T {
137
- unsafe { ops:: atomic_load ( self . v . get ( ) , order) }
144
+ unsafe { ops:: atomic_load ( self . inner_ptr ( ) , order) }
138
145
}
139
146
140
147
/// Stores a value into the `Atomic`.
@@ -148,7 +155,7 @@ impl<T: Copy> Atomic<T> {
148
155
#[ inline]
149
156
pub fn store ( & self , val : T , order : Ordering ) {
150
157
unsafe {
151
- ops:: atomic_store ( self . v . get ( ) , val, order) ;
158
+ ops:: atomic_store ( self . inner_ptr ( ) , val, order) ;
152
159
}
153
160
}
154
161
@@ -158,7 +165,7 @@ impl<T: Copy> Atomic<T> {
158
165
/// of this operation.
159
166
#[ inline]
160
167
pub fn swap ( & self , val : T , order : Ordering ) -> T {
161
- unsafe { ops:: atomic_swap ( self . v . get ( ) , val, order) }
168
+ unsafe { ops:: atomic_swap ( self . inner_ptr ( ) , val, order) }
162
169
}
163
170
164
171
/// Stores a value into the `Atomic` if the current value is the same as the
@@ -181,7 +188,7 @@ impl<T: Copy> Atomic<T> {
181
188
success : Ordering ,
182
189
failure : Ordering ,
183
190
) -> Result < T , T > {
184
- unsafe { ops:: atomic_compare_exchange ( self . v . get ( ) , current, new, success, failure) }
191
+ unsafe { ops:: atomic_compare_exchange ( self . inner_ptr ( ) , current, new, success, failure) }
185
192
}
186
193
187
194
/// Stores a value into the `Atomic` if the current value is the same as the
@@ -206,7 +213,9 @@ impl<T: Copy> Atomic<T> {
206
213
success : Ordering ,
207
214
failure : Ordering ,
208
215
) -> Result < T , T > {
209
- unsafe { ops:: atomic_compare_exchange_weak ( self . v . get ( ) , current, new, success, failure) }
216
+ unsafe {
217
+ ops:: atomic_compare_exchange_weak ( self . inner_ptr ( ) , current, new, success, failure)
218
+ }
210
219
}
211
220
212
221
/// Fetches the value, and applies a function to it that returns an optional
@@ -275,7 +284,7 @@ impl Atomic<bool> {
275
284
/// Returns the previous value.
276
285
#[ inline]
277
286
pub fn fetch_and ( & self , val : bool , order : Ordering ) -> bool {
278
- unsafe { ops:: atomic_and ( self . v . get ( ) , val, order) }
287
+ unsafe { ops:: atomic_and ( self . inner_ptr ( ) , val, order) }
279
288
}
280
289
281
290
/// Logical "or" with a boolean value.
@@ -286,7 +295,7 @@ impl Atomic<bool> {
286
295
/// Returns the previous value.
287
296
#[ inline]
288
297
pub fn fetch_or ( & self , val : bool , order : Ordering ) -> bool {
289
- unsafe { ops:: atomic_or ( self . v . get ( ) , val, order) }
298
+ unsafe { ops:: atomic_or ( self . inner_ptr ( ) , val, order) }
290
299
}
291
300
292
301
/// Logical "xor" with a boolean value.
@@ -297,7 +306,7 @@ impl Atomic<bool> {
297
306
/// Returns the previous value.
298
307
#[ inline]
299
308
pub fn fetch_xor ( & self , val : bool , order : Ordering ) -> bool {
300
- unsafe { ops:: atomic_xor ( self . v . get ( ) , val, order) }
309
+ unsafe { ops:: atomic_xor ( self . inner_ptr ( ) , val, order) }
301
310
}
302
311
}
303
312
@@ -307,31 +316,31 @@ macro_rules! atomic_ops_common {
307
316
/// Add to the current value, returning the previous value.
308
317
#[ inline]
309
318
pub fn fetch_add( & self , val: $t, order: Ordering ) -> $t {
310
- unsafe { ops:: atomic_add( self . v . get ( ) , val, order) }
319
+ unsafe { ops:: atomic_add( self . inner_ptr ( ) , val, order) }
311
320
}
312
321
313
322
/// Subtract from the current value, returning the previous value.
314
323
#[ inline]
315
324
pub fn fetch_sub( & self , val: $t, order: Ordering ) -> $t {
316
- unsafe { ops:: atomic_sub( self . v . get ( ) , val, order) }
325
+ unsafe { ops:: atomic_sub( self . inner_ptr ( ) , val, order) }
317
326
}
318
327
319
328
/// Bitwise and with the current value, returning the previous value.
320
329
#[ inline]
321
330
pub fn fetch_and( & self , val: $t, order: Ordering ) -> $t {
322
- unsafe { ops:: atomic_and( self . v . get ( ) , val, order) }
331
+ unsafe { ops:: atomic_and( self . inner_ptr ( ) , val, order) }
323
332
}
324
333
325
334
/// Bitwise or with the current value, returning the previous value.
326
335
#[ inline]
327
336
pub fn fetch_or( & self , val: $t, order: Ordering ) -> $t {
328
- unsafe { ops:: atomic_or( self . v . get ( ) , val, order) }
337
+ unsafe { ops:: atomic_or( self . inner_ptr ( ) , val, order) }
329
338
}
330
339
331
340
/// Bitwise xor with the current value, returning the previous value.
332
341
#[ inline]
333
342
pub fn fetch_xor( & self , val: $t, order: Ordering ) -> $t {
334
- unsafe { ops:: atomic_xor( self . v . get ( ) , val, order) }
343
+ unsafe { ops:: atomic_xor( self . inner_ptr ( ) , val, order) }
335
344
}
336
345
}
337
346
) * ) ;
@@ -344,13 +353,13 @@ macro_rules! atomic_ops_signed {
344
353
/// Minimum with the current value.
345
354
#[ inline]
346
355
pub fn fetch_min( & self , val: $t, order: Ordering ) -> $t {
347
- unsafe { ops:: atomic_min( self . v . get ( ) , val, order) }
356
+ unsafe { ops:: atomic_min( self . inner_ptr ( ) , val, order) }
348
357
}
349
358
350
359
/// Maximum with the current value.
351
360
#[ inline]
352
361
pub fn fetch_max( & self , val: $t, order: Ordering ) -> $t {
353
- unsafe { ops:: atomic_max( self . v . get ( ) , val, order) }
362
+ unsafe { ops:: atomic_max( self . inner_ptr ( ) , val, order) }
354
363
}
355
364
}
356
365
) *
@@ -364,13 +373,13 @@ macro_rules! atomic_ops_unsigned {
364
373
/// Minimum with the current value.
365
374
#[ inline]
366
375
pub fn fetch_min( & self , val: $t, order: Ordering ) -> $t {
367
- unsafe { ops:: atomic_umin( self . v . get ( ) , val, order) }
376
+ unsafe { ops:: atomic_umin( self . inner_ptr ( ) , val, order) }
368
377
}
369
378
370
379
/// Maximum with the current value.
371
380
#[ inline]
372
381
pub fn fetch_max( & self , val: $t, order: Ordering ) -> $t {
373
- unsafe { ops:: atomic_umax( self . v . get ( ) , val, order) }
382
+ unsafe { ops:: atomic_umax( self . inner_ptr ( ) , val, order) }
374
383
}
375
384
}
376
385
) *
0 commit comments