Skip to content

Commit 6fdcc4f

Browse files
committed
New SPSC queue, now safe and much simpler
This commit implements a new, simplified, SPSC that does not have the reported issues (e.g. not properly wrapping the indexes for non powers-of-2), and the support for multiple different index sizes has been removed for simplicity.
1 parent dfa5d50 commit 6fdcc4f

File tree

10 files changed

+931
-60
lines changed

10 files changed

+931
-60
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1313
- [breaking-change] `HistoryBuffer` is now working with const constructors and non-`Copy` data
1414
- [breaking-change] `HistoryBuffer::as_slice` and others now only return initialized values
1515
- [breaking-change] `MultiCore`/`SingleCore` is now removed from `spsc::Queue`
16-
- [breaking-change] `spsc::Queue::u8()` and `spsc::Queue::u16()` are now unsafe
16+
- [breaking-change] `spsc::Queue` is now `usize` only
17+
- [breaking-change] `spsc::Queue` now sacrifices one element for correctness (see issue #207)
1718
- `Pool` and `MPMC` now works on `thumbv6m`
1819
- [breaking-change] `String` has had `utf8` related methods removed as this can be done via `str`
1920
- [breaking-change] No data structures implement `AsSlice` traits any more, now using `AsRef` and `AsMut`

cfail/ui/freeze.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use heapless::{spsc::Queue};
1+
use heapless::spsc::Queue;
22

33
fn main() {
4-
let mut q: Queue<u8, _, 4> = Queue::new();
4+
let mut q: Queue<u8, 4> = Queue::new();
55

66
let (_p, mut _c) = q.split();
77
q.enqueue(0).unwrap();

cfail/ui/not-send.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use core::marker::PhantomData;
44

55
use heapless::{
66
spsc::{Consumer, Producer, Queue},
7+
HistoryBuffer, Vec,
78
};
89

910
type NotSend = PhantomData<*const ()>;
@@ -15,8 +16,9 @@ where
1516
}
1617

1718
fn main() {
18-
is_send::<Consumer<NotSend, _, 4>>();
19-
is_send::<Producer<NotSend, _, 4>>();
20-
is_send::<Queue<NotSend, _, 4>>();
21-
is_send::<heapless::Vec<NotSend, 4>>();
19+
is_send::<Consumer<NotSend, 4>>();
20+
is_send::<Producer<NotSend, 4>>();
21+
is_send::<Queue<NotSend, 4>>();
22+
is_send::<Vec<NotSend, 4>>();
23+
is_send::<HistoryBuffer<NotSend, 4>>();
2224
}

cfail/ui/not-send.stderr

+51-31
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,89 @@
11
error[E0277]: `*const ()` cannot be sent between threads safely
2-
--> $DIR/not-send.rs:18:5
2+
--> $DIR/not-send.rs:19:5
33
|
4-
11 | fn is_send<T>()
4+
12 | fn is_send<T>()
55
| ------- required by a bound in this
6-
12 | where
7-
13 | T: Send,
6+
13 | where
7+
14 | T: Send,
88
| ---- required by this bound in `is_send`
99
...
10-
18 | is_send::<Consumer<NotSend, _, 4>>();
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
10+
19 | is_send::<Consumer<NotSend, 4>>();
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
1212
|
1313
= help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()`
1414
= note: required because it appears within the type `PhantomData<*const ()>`
15-
= note: required because of the requirements on the impl of `Send` for `Consumer<'_, PhantomData<*const ()>, _, 4_usize>`
15+
= note: required because of the requirements on the impl of `Send` for `Consumer<'_, PhantomData<*const ()>, 4_usize>`
1616

1717
error[E0277]: `*const ()` cannot be sent between threads safely
18-
--> $DIR/not-send.rs:19:5
18+
--> $DIR/not-send.rs:20:5
1919
|
20-
11 | fn is_send<T>()
20+
12 | fn is_send<T>()
2121
| ------- required by a bound in this
22-
12 | where
23-
13 | T: Send,
22+
13 | where
23+
14 | T: Send,
2424
| ---- required by this bound in `is_send`
2525
...
26-
19 | is_send::<Producer<NotSend, _, 4>>();
27-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
26+
20 | is_send::<Producer<NotSend, 4>>();
27+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
2828
|
2929
= help: within `PhantomData<*const ()>`, the trait `Send` is not implemented for `*const ()`
3030
= note: required because it appears within the type `PhantomData<*const ()>`
31-
= note: required because of the requirements on the impl of `Send` for `Producer<'_, PhantomData<*const ()>, _, 4_usize>`
31+
= note: required because of the requirements on the impl of `Send` for `Producer<'_, PhantomData<*const ()>, 4_usize>`
3232

3333
error[E0277]: `*const ()` cannot be sent between threads safely
34-
--> $DIR/not-send.rs:20:5
34+
--> $DIR/not-send.rs:21:5
3535
|
36-
11 | fn is_send<T>()
36+
12 | fn is_send<T>()
3737
| ------- required by a bound in this
38-
12 | where
39-
13 | T: Send,
38+
13 | where
39+
14 | T: Send,
4040
| ---- required by this bound in `is_send`
4141
...
42-
20 | is_send::<Queue<NotSend, _, 4>>();
43-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
42+
21 | is_send::<Queue<NotSend, 4>>();
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
4444
|
45-
= help: within `Queue<PhantomData<*const ()>, _, 4_usize>`, the trait `Send` is not implemented for `*const ()`
45+
= help: within `Queue<PhantomData<*const ()>, 4_usize>`, the trait `Send` is not implemented for `*const ()`
4646
= note: required because it appears within the type `PhantomData<*const ()>`
47-
= note: required because it appears within the type `[PhantomData<*const ()>; 4]`
48-
= note: required because it appears within the type `ManuallyDrop<[PhantomData<*const ()>; 4]>`
49-
= note: required because it appears within the type `MaybeUninit<[PhantomData<*const ()>; 4]>`
50-
= note: required because it appears within the type `Queue<PhantomData<*const ()>, _, 4_usize>`
47+
= note: required because it appears within the type `ManuallyDrop<PhantomData<*const ()>>`
48+
= note: required because it appears within the type `MaybeUninit<PhantomData<*const ()>>`
49+
= note: required because it appears within the type `UnsafeCell<MaybeUninit<PhantomData<*const ()>>>`
50+
= note: required because it appears within the type `[UnsafeCell<MaybeUninit<PhantomData<*const ()>>>; 4]`
51+
= note: required because it appears within the type `Queue<PhantomData<*const ()>, 4_usize>`
5152

5253
error[E0277]: `*const ()` cannot be sent between threads safely
53-
--> $DIR/not-send.rs:21:5
54+
--> $DIR/not-send.rs:22:5
5455
|
55-
11 | fn is_send<T>()
56+
12 | fn is_send<T>()
5657
| ------- required by a bound in this
57-
12 | where
58-
13 | T: Send,
58+
13 | where
59+
14 | T: Send,
5960
| ---- required by this bound in `is_send`
6061
...
61-
21 | is_send::<heapless::Vec<NotSend, 4>>();
62-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
62+
22 | is_send::<Vec<NotSend, 4>>();
63+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
6364
|
6465
= help: within `heapless::Vec<PhantomData<*const ()>, 4_usize>`, the trait `Send` is not implemented for `*const ()`
6566
= note: required because it appears within the type `PhantomData<*const ()>`
6667
= note: required because it appears within the type `[PhantomData<*const ()>; 4]`
6768
= note: required because it appears within the type `ManuallyDrop<[PhantomData<*const ()>; 4]>`
6869
= note: required because it appears within the type `MaybeUninit<[PhantomData<*const ()>; 4]>`
6970
= note: required because it appears within the type `heapless::Vec<PhantomData<*const ()>, 4_usize>`
71+
72+
error[E0277]: `*const ()` cannot be sent between threads safely
73+
--> $DIR/not-send.rs:23:5
74+
|
75+
12 | fn is_send<T>()
76+
| ------- required by a bound in this
77+
13 | where
78+
14 | T: Send,
79+
| ---- required by this bound in `is_send`
80+
...
81+
23 | is_send::<HistoryBuffer<NotSend, 4>>();
82+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
83+
|
84+
= help: within `HistoryBuffer<PhantomData<*const ()>, 4_usize>`, the trait `Send` is not implemented for `*const ()`
85+
= note: required because it appears within the type `PhantomData<*const ()>`
86+
= note: required because it appears within the type `ManuallyDrop<PhantomData<*const ()>>`
87+
= note: required because it appears within the type `MaybeUninit<PhantomData<*const ()>>`
88+
= note: required because it appears within the type `[MaybeUninit<PhantomData<*const ()>>; 4]`
89+
= note: required because it appears within the type `HistoryBuffer<PhantomData<*const ()>, 4_usize>`

src/histbuf.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use core::slice;
1212
/// ```
1313
/// use heapless::HistoryBuffer;
1414
///
15-
/// // Initialize a new buffer with 8 elements, all initially zero.
15+
/// // Initialize a new buffer with 8 elements.
1616
/// let mut buf = HistoryBuffer::<_, 8>::new();
1717
///
1818
/// // Starts with no data

0 commit comments

Comments
 (0)