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,53 @@ 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
18
- pub unsafe trait Uxx : Into < usize > + Send {
21
+ /// This trait is sealed and cannot be implemented outside of `heapless`.
22
+ pub unsafe trait Uxx : Into < usize > + Send + private :: Sealed {
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
+ mod private {
58
+ pub trait Sealed { }
59
+
60
+ impl Sealed for usize { }
61
+ #[ cfg( feature = "smaller-atomics" ) ]
62
+ impl Sealed for u8 { }
63
+ #[ cfg( feature = "smaller-atomics" ) ]
64
+ impl Sealed for u16 { }
65
+ }
66
+
67
+ #[ cfg( feature = "smaller-atomics" ) ]
23
68
unsafe impl Uxx for u8 {
24
69
fn truncate ( x : usize ) -> Self {
25
70
let max = :: core:: u8:: MAX ;
@@ -31,6 +76,7 @@ unsafe impl Uxx for u8 {
31
76
}
32
77
}
33
78
79
+ #[ cfg( feature = "smaller-atomics" ) ]
34
80
unsafe impl Uxx for u16 {
35
81
fn truncate ( x : usize ) -> Self {
36
82
let max = :: core:: u16:: MAX ;
@@ -46,6 +92,23 @@ unsafe impl Uxx for usize {
46
92
fn truncate ( x : usize ) -> Self {
47
93
x
48
94
}
95
+
96
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
97
+ fn load_acquire ( x : * mut Self ) -> Self {
98
+ unsafe { ( * ( x as * mut AtomicUsize ) ) . load ( Ordering :: Acquire ) }
99
+ }
100
+
101
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
102
+ fn load_relaxed ( x : * mut Self ) -> Self {
103
+ unsafe { ( * ( x as * mut AtomicUsize ) ) . load ( Ordering :: Relaxed ) }
104
+ }
105
+
106
+ #[ cfg( not( feature = "smaller-atomics" ) ) ]
107
+ fn store_release ( x : * mut Self , val : Self ) {
108
+ unsafe {
109
+ ( * ( x as * mut AtomicUsize ) ) . store ( val, Ordering :: Release ) ;
110
+ }
111
+ }
49
112
}
50
113
51
114
// Atomic{U8,U16, Usize} with no CAS operations that works on targets that have "no atomic support"
@@ -61,28 +124,26 @@ impl<U> Atomic<U>
61
124
where
62
125
U : Uxx ,
63
126
{
64
- const_fn ! (
65
- const fn new( v: U ) -> Atomic <U > {
66
- Atomic {
67
- v: UnsafeCell :: new( v) ,
68
- }
127
+ const_fn ! ( const fn new( v: U ) -> Atomic <U > {
128
+ Atomic {
129
+ v: UnsafeCell :: new( v) ,
69
130
}
70
- ) ;
131
+ } ) ;
71
132
72
133
fn get_mut ( & mut self ) -> & mut U {
73
134
unsafe { & mut * self . v . get ( ) }
74
135
}
75
136
76
137
fn load_acquire ( & self ) -> U {
77
- unsafe { intrinsics :: atomic_load_acq ( self . v . get ( ) ) }
138
+ U :: load_acquire ( self . v . get ( ) )
78
139
}
79
140
80
141
fn load_relaxed ( & self ) -> U {
81
- unsafe { intrinsics :: atomic_load_relaxed ( self . v . get ( ) ) }
142
+ U :: load_relaxed ( self . v . get ( ) )
82
143
}
83
144
84
145
fn store_release ( & self , val : U ) {
85
- unsafe { intrinsics :: atomic_store_rel ( self . v . get ( ) , val) }
146
+ U :: store_release ( self . v . get ( ) , val)
86
147
}
87
148
}
88
149
@@ -269,7 +330,6 @@ macro_rules! impl_ {
269
330
N : Add <U1 > + Unsigned ,
270
331
Sum <N , U1 >: ArrayLength <T >,
271
332
{
272
-
273
333
const_fn!(
274
334
/// Creates an empty ring buffer with a fixed capacity of `N`
275
335
pub const fn $uxx( ) -> Self {
@@ -357,7 +417,6 @@ where
357
417
N : Add < U1 > + Unsigned ,
358
418
Sum < N , U1 > : ArrayLength < T > ,
359
419
{
360
-
361
420
const_fn ! (
362
421
/// Alias for [`RingBuffer::usize`](struct.RingBuffer.html#method.usize)
363
422
pub const fn new( ) -> Self {
@@ -366,7 +425,9 @@ where
366
425
) ;
367
426
}
368
427
428
+ #[ cfg( feature = "smaller-atomics" ) ]
369
429
impl_ ! ( u8 ) ;
430
+ #[ cfg( feature = "smaller-atomics" ) ]
370
431
impl_ ! ( u16 ) ;
371
432
impl_ ! ( usize ) ;
372
433
@@ -548,6 +609,7 @@ mod tests {
548
609
}
549
610
550
611
#[ test]
612
+ #[ cfg( feature = "smaller-atomics" ) ]
551
613
fn u8 ( ) {
552
614
let mut rb: RingBuffer < u8 , U256 , _ > = RingBuffer :: u8 ( ) ;
553
615
0 commit comments