@@ -5,6 +5,7 @@ use core::num::{
5
5
NonZeroU64 , NonZeroU8 , NonZeroUsize , Wrapping ,
6
6
} ;
7
7
use core:: ptr:: NonNull ;
8
+ use core:: sync:: atomic;
8
9
9
10
use crate :: Encoding ;
10
11
@@ -168,6 +169,9 @@ encode_impls!(
168
169
u64 => ULongLong ,
169
170
f32 => Float ,
170
171
f64 => Double ,
172
+
173
+ // TODO: i128 & u128
174
+ // https://github.com/rust-lang/rust/issues/54341
171
175
) ;
172
176
173
177
// TODO: Structs in core::arch?
@@ -285,8 +289,72 @@ encode_impls_nonzero!(
285
289
NonZeroUsize => usize ,
286
290
) ;
287
291
288
- // Note: I'm not sure atomic integers would be safe, since they might need the
289
- // Objective-C runtime to insert proper memory fences and ordering stuff?
292
+ /// Simple helper for implementing for atomic types.
293
+ macro_rules! encode_atomic_impls {
294
+ ( $(
295
+ $( #[ $m: meta] ) *
296
+ $atomic: ident => $type: ty,
297
+ ) * ) => ( $(
298
+ // SAFETY: C11 `_Atomic` types use compatible synchronization
299
+ // primitives, and the atomic type is guaranteed to have the same
300
+ // in-memory representation as the underlying type.
301
+ $( #[ $m] ) *
302
+ unsafe impl Encode for atomic:: $atomic {
303
+ const ENCODING : Encoding <' static > = Encoding :: Atomic ( & <$type>:: ENCODING ) ;
304
+ }
305
+
306
+ $( #[ $m] ) *
307
+ unsafe impl RefEncode for atomic:: $atomic {
308
+ const ENCODING_REF : Encoding <' static > = Encoding :: Pointer ( & Self :: ENCODING ) ;
309
+ }
310
+ ) * ) ;
311
+ }
312
+
313
+ encode_atomic_impls ! (
314
+ #[ cfg( target_has_atomic = "8" ) ]
315
+ AtomicBool => bool ,
316
+ #[ cfg( target_has_atomic = "8" ) ]
317
+ AtomicI8 => i8 ,
318
+ #[ cfg( target_has_atomic = "8" ) ]
319
+ AtomicU8 => u8 ,
320
+
321
+ #[ cfg( target_has_atomic = "16" ) ]
322
+ AtomicI16 => i16 ,
323
+ #[ cfg( target_has_atomic = "16" ) ]
324
+ AtomicU16 => u16 ,
325
+
326
+ #[ cfg( target_has_atomic = "32" ) ]
327
+ AtomicI32 => i32 ,
328
+ #[ cfg( target_has_atomic = "32" ) ]
329
+ AtomicU32 => u32 ,
330
+
331
+ #[ cfg( target_has_atomic = "64" ) ]
332
+ AtomicI64 => i64 ,
333
+ #[ cfg( target_has_atomic = "64" ) ]
334
+ AtomicU64 => u64 ,
335
+
336
+ // TODO
337
+ // #[cfg(target_has_atomic = "128")]
338
+ // AtomicI128 => i128,
339
+ // #[cfg(target_has_atomic = "128")]
340
+ // AtomicU128 => u128,
341
+
342
+ #[ cfg( target_has_atomic = "ptr" ) ]
343
+ AtomicIsize => isize ,
344
+ #[ cfg( target_has_atomic = "ptr" ) ]
345
+ AtomicUsize => usize ,
346
+ ) ;
347
+
348
+ // SAFETY: Guaranteed to have the same in-memory representation as `*mut T`.
349
+ #[ cfg( target_has_atomic = "ptr" ) ]
350
+ unsafe impl < T : RefEncode > Encode for atomic:: AtomicPtr < T > {
351
+ const ENCODING : Encoding < ' static > = Encoding :: Atomic ( & T :: ENCODING_REF ) ;
352
+ }
353
+
354
+ #[ cfg( target_has_atomic = "ptr" ) ]
355
+ unsafe impl < T : RefEncode > RefEncode for atomic:: AtomicPtr < T > {
356
+ const ENCODING_REF : Encoding < ' static > = Encoding :: Pointer ( & Self :: ENCODING ) ;
357
+ }
290
358
291
359
/// [`Encode`] is implemented manually for `*const c_void`, instead of
292
360
/// implementing [`RefEncode`], to discourage creating `&c_void`.
@@ -539,6 +607,7 @@ encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L);
539
607
540
608
#[ cfg( test) ]
541
609
mod tests {
610
+ use super :: atomic:: * ;
542
611
use super :: * ;
543
612
544
613
#[ test]
@@ -568,6 +637,29 @@ mod tests {
568
637
) ;
569
638
}
570
639
640
+ #[ test]
641
+ fn test_atomic ( ) {
642
+ assert_eq ! ( AtomicI32 :: ENCODING , Encoding :: Atomic ( & Encoding :: Int ) ) ;
643
+ assert_eq ! (
644
+ AtomicI32 :: ENCODING_REF ,
645
+ Encoding :: Pointer ( & Encoding :: Atomic ( & Encoding :: Int ) )
646
+ ) ;
647
+ assert_eq ! (
648
+ AtomicPtr :: <i32 >:: ENCODING ,
649
+ Encoding :: Atomic ( & Encoding :: Pointer ( & Encoding :: Int ) )
650
+ ) ;
651
+
652
+ assert_eq ! ( AtomicI8 :: ENCODING , Encoding :: Atomic ( & Encoding :: Char ) ) ;
653
+ assert_eq ! (
654
+ AtomicI8 :: ENCODING_REF ,
655
+ Encoding :: Pointer ( & Encoding :: Atomic ( & Encoding :: Char ) )
656
+ ) ;
657
+ assert_eq ! (
658
+ AtomicPtr :: <i8 >:: ENCODING ,
659
+ Encoding :: Atomic ( & Encoding :: String )
660
+ ) ;
661
+ }
662
+
571
663
#[ test]
572
664
fn test_void ( ) {
573
665
// TODO: Remove this
0 commit comments