1
1
//! Ring buffer
2
2
3
3
use core:: cell:: UnsafeCell ;
4
+ #[ cfg( feature = "smaller-atomics" ) ]
5
+ use core:: intrinsics;
4
6
use core:: ops:: Add ;
5
- use core:: { intrinsics, ptr} ;
7
+ use core:: ptr;
8
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
9
+ use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
6
10
7
11
use generic_array:: typenum:: { Sum , U1 , Unsigned } ;
8
12
use generic_array:: { ArrayLength , GenericArray } ;
@@ -14,12 +18,43 @@ mod spsc;
14
18
15
19
/// Types that can be used as `RingBuffer` indices: `u8`, `u16` and `usize
16
20
///
17
- /// Do not implement this trait yourself
21
+ /// This trait is sealed and cannot be implemented outside of `heapless`.
18
22
pub unsafe trait Uxx : Into < usize > + Send {
19
23
#[ doc( hidden) ]
20
24
fn truncate ( x : usize ) -> Self ;
25
+
26
+ #[ cfg( feature = "smaller-atomics" ) ]
27
+ #[ doc( hidden) ]
28
+ fn load_acquire ( x : * mut Self ) -> Self {
29
+ unsafe { intrinsics:: atomic_load_acq ( x) }
30
+ }
31
+
32
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
33
+ #[ doc( hidden) ]
34
+ fn load_acquire ( x : * mut Self ) -> Self ;
35
+
36
+ #[ cfg( feature = "smaller-atomics" ) ]
37
+ #[ doc( hidden) ]
38
+ fn load_relaxed ( x : * mut Self ) -> Self {
39
+ unsafe { intrinsics:: atomic_load_relaxed ( x) }
40
+ }
41
+
42
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
43
+ #[ doc( hidden) ]
44
+ fn load_relaxed ( x : * mut Self ) -> Self ;
45
+
46
+ #[ cfg( feature = "smaller-atomics" ) ]
47
+ #[ doc( hidden) ]
48
+ fn store_release ( x : * mut Self , val : Self ) {
49
+ unsafe { intrinsics:: atomic_store_rel ( x, val) }
50
+ }
51
+
52
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
53
+ #[ doc( hidden) ]
54
+ fn store_release ( x : * mut Self , val : Self ) ;
21
55
}
22
56
57
+ #[ cfg( feature = "smaller-atomics" ) ]
23
58
unsafe impl Uxx for u8 {
24
59
fn truncate ( x : usize ) -> Self {
25
60
let max = :: core:: u8:: MAX ;
@@ -31,6 +66,7 @@ unsafe impl Uxx for u8 {
31
66
}
32
67
}
33
68
69
+ #[ cfg( feature = "smaller-atomics" ) ]
34
70
unsafe impl Uxx for u16 {
35
71
fn truncate ( x : usize ) -> Self {
36
72
let max = :: core:: u16:: MAX ;
@@ -46,6 +82,23 @@ unsafe impl Uxx for usize {
46
82
fn truncate ( x : usize ) -> Self {
47
83
x
48
84
}
85
+
86
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
87
+ fn load_acquire ( x : * mut Self ) -> Self {
88
+ unsafe { ( * ( x as * mut AtomicUsize ) ) . load ( Ordering :: Acquire ) }
89
+ }
90
+
91
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
92
+ fn load_relaxed ( x : * mut Self ) -> Self {
93
+ unsafe { ( * ( x as * mut AtomicUsize ) ) . load ( Ordering :: Relaxed ) }
94
+ }
95
+
96
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
97
+ fn store_release ( x : * mut Self , val : Self ) {
98
+ unsafe {
99
+ ( * ( x as * mut AtomicUsize ) ) . store ( val, Ordering :: Release ) ;
100
+ }
101
+ }
49
102
}
50
103
51
104
// Atomic{U8,U16, Usize} with no CAS operations that works on targets that have "no atomic support"
@@ -61,28 +114,26 @@ impl<U> Atomic<U>
61
114
where
62
115
U : Uxx ,
63
116
{
64
- const_fn ! (
65
- const fn new( v: U ) -> Atomic <U > {
66
- Atomic {
67
- v: UnsafeCell :: new( v) ,
68
- }
117
+ const_fn ! ( const fn new( v: U ) -> Atomic <U > {
118
+ Atomic {
119
+ v: UnsafeCell :: new( v) ,
69
120
}
70
- ) ;
121
+ } ) ;
71
122
72
123
fn get_mut ( & mut self ) -> & mut U {
73
124
unsafe { & mut * self . v . get ( ) }
74
125
}
75
126
76
127
fn load_acquire ( & self ) -> U {
77
- unsafe { intrinsics :: atomic_load_acq ( self . v . get ( ) ) }
128
+ U :: load_acquire ( self . v . get ( ) )
78
129
}
79
130
80
131
fn load_relaxed ( & self ) -> U {
81
- unsafe { intrinsics :: atomic_load_relaxed ( self . v . get ( ) ) }
132
+ U :: load_relaxed ( self . v . get ( ) )
82
133
}
83
134
84
135
fn store_release ( & self , val : U ) {
85
- unsafe { intrinsics :: atomic_store_rel ( self . v . get ( ) , val) }
136
+ U :: store_release ( self . v . get ( ) , val)
86
137
}
87
138
}
88
139
@@ -269,7 +320,6 @@ macro_rules! impl_ {
269
320
N : Add <U1 > + Unsigned ,
270
321
Sum <N , U1 >: ArrayLength <T >,
271
322
{
272
-
273
323
const_fn!(
274
324
/// Creates an empty ring buffer with a fixed capacity of `N`
275
325
pub const fn $uxx( ) -> Self {
@@ -357,7 +407,6 @@ where
357
407
N : Add < U1 > + Unsigned ,
358
408
Sum < N , U1 > : ArrayLength < T > ,
359
409
{
360
-
361
410
const_fn ! (
362
411
/// Alias for [`RingBuffer::usize`](struct.RingBuffer.html#method.usize)
363
412
pub const fn new( ) -> Self {
@@ -366,7 +415,9 @@ where
366
415
) ;
367
416
}
368
417
418
+ #[ cfg( feature = "smaller-atomics" ) ]
369
419
impl_ ! ( u8 ) ;
420
+ #[ cfg( feature = "smaller-atomics" ) ]
370
421
impl_ ! ( u16 ) ;
371
422
impl_ ! ( usize ) ;
372
423
@@ -548,6 +599,7 @@ mod tests {
548
599
}
549
600
550
601
#[ test]
602
+ #[ cfg( feature = "smaller-atomics" ) ]
551
603
fn u8 ( ) {
552
604
let mut rb: RingBuffer < u8 , U256 , _ > = RingBuffer :: u8 ( ) ;
553
605
0 commit comments