aboutsummaryrefslogtreecommitdiff
path: root/embassy-sync
diff options
context:
space:
mode:
authorFrostie314159 <[email protected]>2024-03-21 14:17:03 +0100
committerGitHub <[email protected]>2024-03-21 14:17:03 +0100
commit7efe8e0005ca75c3753081848e8b176f8ac3a9ba (patch)
tree3690b3b873b4643a07e29b60bf92596a819d30f0 /embassy-sync
parent8707462ec23807782796fbac4295bc5bce9ff136 (diff)
parent29d388042cdbd76d46f66ebe58cc580edb4515f8 (diff)
Merge branch 'embassy-rs:main' into reset-at-after
Diffstat (limited to 'embassy-sync')
-rw-r--r--embassy-sync/Cargo.toml1
-rw-r--r--embassy-sync/README.md14
-rw-r--r--embassy-sync/build.rs13
-rw-r--r--embassy-sync/src/channel.rs37
-rw-r--r--embassy-sync/src/fmt.rs3
-rw-r--r--embassy-sync/src/lib.rs2
-rw-r--r--embassy-sync/src/priority_channel.rs2
-rw-r--r--embassy-sync/src/ring_buffer.rs22
-rw-r--r--embassy-sync/src/signal.rs16
-rw-r--r--embassy-sync/src/zerocopy_channel.rs7
10 files changed, 67 insertions, 50 deletions
diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml
index 38b0e5d30..85673026c 100644
--- a/embassy-sync/Cargo.toml
+++ b/embassy-sync/Cargo.toml
@@ -4,6 +4,7 @@ version = "0.5.0"
4edition = "2021" 4edition = "2021"
5description = "no-std, no-alloc synchronization primitives with async support" 5description = "no-std, no-alloc synchronization primitives with async support"
6repository = "https://github.com/embassy-rs/embassy" 6repository = "https://github.com/embassy-rs/embassy"
7documentation = "https://docs.embassy.dev/embassy-sync"
7readme = "README.md" 8readme = "README.md"
8license = "MIT OR Apache-2.0" 9license = "MIT OR Apache-2.0"
9categories = [ 10categories = [
diff --git a/embassy-sync/README.md b/embassy-sync/README.md
index 55618f72d..c2e13799e 100644
--- a/embassy-sync/README.md
+++ b/embassy-sync/README.md
@@ -17,17 +17,3 @@ Synchronization primitives and data structures with async support:
17## Interoperability 17## Interoperability
18 18
19Futures from this crate can run on any executor. 19Futures from this crate can run on any executor.
20
21## Minimum supported Rust version (MSRV)
22
23Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release.
24
25## License
26
27This work is licensed under either of
28
29- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
30 <http://www.apache.org/licenses/LICENSE-2.0>)
31- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
32
33at your option.
diff --git a/embassy-sync/build.rs b/embassy-sync/build.rs
index 0a796b881..afd76dad1 100644
--- a/embassy-sync/build.rs
+++ b/embassy-sync/build.rs
@@ -1,21 +1,8 @@
1use std::env; 1use std::env;
2use std::ffi::OsString;
3use std::process::Command;
4 2
5fn main() { 3fn main() {
6 println!("cargo:rerun-if-changed=build.rs"); 4 println!("cargo:rerun-if-changed=build.rs");
7 5
8 let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc"));
9
10 let output = Command::new(rustc)
11 .arg("--version")
12 .output()
13 .expect("failed to run `rustc --version`");
14
15 if String::from_utf8_lossy(&output.stdout).contains("nightly") {
16 println!("cargo:rustc-cfg=nightly");
17 }
18
19 let target = env::var("TARGET").unwrap(); 6 let target = env::var("TARGET").unwrap();
20 7
21 if target.starts_with("thumbv6m-") { 8 if target.starts_with("thumbv6m-") {
diff --git a/embassy-sync/src/channel.rs b/embassy-sync/src/channel.rs
index ff7129303..48f4dafd6 100644
--- a/embassy-sync/src/channel.rs
+++ b/embassy-sync/src/channel.rs
@@ -263,6 +263,12 @@ impl<'ch, T> Future for DynamicReceiveFuture<'ch, T> {
263 } 263 }
264} 264}
265 265
266impl<'ch, M: RawMutex, T, const N: usize> From<ReceiveFuture<'ch, M, T, N>> for DynamicReceiveFuture<'ch, T> {
267 fn from(value: ReceiveFuture<'ch, M, T, N>) -> Self {
268 Self { channel: value.channel }
269 }
270}
271
266/// Future returned by [`Channel::send`] and [`Sender::send`]. 272/// Future returned by [`Channel::send`] and [`Sender::send`].
267#[must_use = "futures do nothing unless you `.await` or poll them"] 273#[must_use = "futures do nothing unless you `.await` or poll them"]
268pub struct SendFuture<'ch, M, T, const N: usize> 274pub struct SendFuture<'ch, M, T, const N: usize>
@@ -321,6 +327,15 @@ impl<'ch, T> Future for DynamicSendFuture<'ch, T> {
321 327
322impl<'ch, T> Unpin for DynamicSendFuture<'ch, T> {} 328impl<'ch, T> Unpin for DynamicSendFuture<'ch, T> {}
323 329
330impl<'ch, M: RawMutex, T, const N: usize> From<SendFuture<'ch, M, T, N>> for DynamicSendFuture<'ch, T> {
331 fn from(value: SendFuture<'ch, M, T, N>) -> Self {
332 Self {
333 channel: value.channel,
334 message: value.message,
335 }
336 }
337}
338
324pub(crate) trait DynamicChannel<T> { 339pub(crate) trait DynamicChannel<T> {
325 fn try_send_with_context(&self, message: T, cx: Option<&mut Context<'_>>) -> Result<(), TrySendError<T>>; 340 fn try_send_with_context(&self, message: T, cx: Option<&mut Context<'_>>) -> Result<(), TrySendError<T>>;
326 341
@@ -507,6 +522,16 @@ where
507 Receiver { channel: self } 522 Receiver { channel: self }
508 } 523 }
509 524
525 /// Get a sender for this channel using dynamic dispatch.
526 pub fn dyn_sender(&self) -> DynamicSender<'_, T> {
527 DynamicSender { channel: self }
528 }
529
530 /// Get a receiver for this channel using dynamic dispatch.
531 pub fn dyn_receiver(&self) -> DynamicReceiver<'_, T> {
532 DynamicReceiver { channel: self }
533 }
534
510 /// Send a value, waiting until there is capacity. 535 /// Send a value, waiting until there is capacity.
511 /// 536 ///
512 /// Sending completes when the value has been pushed to the channel's queue. 537 /// Sending completes when the value has been pushed to the channel's queue.
@@ -648,7 +673,7 @@ mod tests {
648 } 673 }
649 674
650 #[test] 675 #[test]
651 fn dynamic_dispatch() { 676 fn dynamic_dispatch_into() {
652 let c = Channel::<NoopRawMutex, u32, 3>::new(); 677 let c = Channel::<NoopRawMutex, u32, 3>::new();
653 let s: DynamicSender<'_, u32> = c.sender().into(); 678 let s: DynamicSender<'_, u32> = c.sender().into();
654 let r: DynamicReceiver<'_, u32> = c.receiver().into(); 679 let r: DynamicReceiver<'_, u32> = c.receiver().into();
@@ -657,6 +682,16 @@ mod tests {
657 assert_eq!(r.try_receive().unwrap(), 1); 682 assert_eq!(r.try_receive().unwrap(), 1);
658 } 683 }
659 684
685 #[test]
686 fn dynamic_dispatch_constructor() {
687 let c = Channel::<NoopRawMutex, u32, 3>::new();
688 let s = c.dyn_sender();
689 let r = c.dyn_receiver();
690
691 assert!(s.try_send(1).is_ok());
692 assert_eq!(r.try_receive().unwrap(), 1);
693 }
694
660 #[futures_test::test] 695 #[futures_test::test]
661 async fn receiver_receives_given_try_send_async() { 696 async fn receiver_receives_given_try_send_async() {
662 let executor = ThreadPool::new().unwrap(); 697 let executor = ThreadPool::new().unwrap();
diff --git a/embassy-sync/src/fmt.rs b/embassy-sync/src/fmt.rs
index 78e583c1c..2ac42c557 100644
--- a/embassy-sync/src/fmt.rs
+++ b/embassy-sync/src/fmt.rs
@@ -1,5 +1,5 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused)]
3 3
4use core::fmt::{Debug, Display, LowerHex}; 4use core::fmt::{Debug, Display, LowerHex};
5 5
@@ -229,7 +229,6 @@ impl<T, E> Try for Result<T, E> {
229 } 229 }
230} 230}
231 231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]); 232pub(crate) struct Bytes<'a>(pub &'a [u8]);
234 233
235impl<'a> Debug for Bytes<'a> { 234impl<'a> Debug for Bytes<'a> {
diff --git a/embassy-sync/src/lib.rs b/embassy-sync/src/lib.rs
index b0ccfde57..d88c76db5 100644
--- a/embassy-sync/src/lib.rs
+++ b/embassy-sync/src/lib.rs
@@ -1,6 +1,4 @@
1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] 1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)]
2#![cfg_attr(nightly, feature(async_fn_in_trait, impl_trait_projections))]
3#![cfg_attr(nightly, allow(stable_features, unknown_lints))]
4#![allow(async_fn_in_trait)] 2#![allow(async_fn_in_trait)]
5#![allow(clippy::new_without_default)] 3#![allow(clippy::new_without_default)]
6#![doc = include_str!("../README.md")] 4#![doc = include_str!("../README.md")]
diff --git a/embassy-sync/src/priority_channel.rs b/embassy-sync/src/priority_channel.rs
index bd75c0135..e77678c24 100644
--- a/embassy-sync/src/priority_channel.rs
+++ b/embassy-sync/src/priority_channel.rs
@@ -325,7 +325,7 @@ where
325/// 325///
326/// Sent data may be reordered based on their priorty within the channel. 326/// Sent data may be reordered based on their priorty within the channel.
327/// For example, in a [`Max`](heapless::binary_heap::Max) [`PriorityChannel`] 327/// For example, in a [`Max`](heapless::binary_heap::Max) [`PriorityChannel`]
328/// containing `u32`'s, data sent in the following order `[1, 2, 3]` will be recieved as `[3, 2, 1]`. 328/// containing `u32`'s, data sent in the following order `[1, 2, 3]` will be received as `[3, 2, 1]`.
329pub struct PriorityChannel<M, T, K, const N: usize> 329pub struct PriorityChannel<M, T, K, const N: usize>
330where 330where
331 T: Ord, 331 T: Ord,
diff --git a/embassy-sync/src/ring_buffer.rs b/embassy-sync/src/ring_buffer.rs
index d95ffa7c9..81e60c42b 100644
--- a/embassy-sync/src/ring_buffer.rs
+++ b/embassy-sync/src/ring_buffer.rs
@@ -3,7 +3,7 @@ use core::ops::Range;
3pub struct RingBuffer<const N: usize> { 3pub struct RingBuffer<const N: usize> {
4 start: usize, 4 start: usize,
5 end: usize, 5 end: usize,
6 empty: bool, 6 full: bool,
7} 7}
8 8
9impl<const N: usize> RingBuffer<N> { 9impl<const N: usize> RingBuffer<N> {
@@ -11,13 +11,13 @@ impl<const N: usize> RingBuffer<N> {
11 Self { 11 Self {
12 start: 0, 12 start: 0,
13 end: 0, 13 end: 0,
14 empty: true, 14 full: false,
15 } 15 }
16 } 16 }
17 17
18 pub fn push_buf(&mut self) -> Range<usize> { 18 pub fn push_buf(&mut self) -> Range<usize> {
19 if self.start == self.end && !self.empty { 19 if self.is_full() {
20 trace!(" ringbuf: push_buf empty"); 20 trace!(" ringbuf: push_buf full");
21 return 0..0; 21 return 0..0;
22 } 22 }
23 23
@@ -38,11 +38,11 @@ impl<const N: usize> RingBuffer<N> {
38 } 38 }
39 39
40 self.end = self.wrap(self.end + n); 40 self.end = self.wrap(self.end + n);
41 self.empty = false; 41 self.full = self.start == self.end;
42 } 42 }
43 43
44 pub fn pop_buf(&mut self) -> Range<usize> { 44 pub fn pop_buf(&mut self) -> Range<usize> {
45 if self.empty { 45 if self.is_empty() {
46 trace!(" ringbuf: pop_buf empty"); 46 trace!(" ringbuf: pop_buf empty");
47 return 0..0; 47 return 0..0;
48 } 48 }
@@ -64,20 +64,20 @@ impl<const N: usize> RingBuffer<N> {
64 } 64 }
65 65
66 self.start = self.wrap(self.start + n); 66 self.start = self.wrap(self.start + n);
67 self.empty = self.start == self.end; 67 self.full = false;
68 } 68 }
69 69
70 pub fn is_full(&self) -> bool { 70 pub fn is_full(&self) -> bool {
71 self.start == self.end && !self.empty 71 self.full
72 } 72 }
73 73
74 pub fn is_empty(&self) -> bool { 74 pub fn is_empty(&self) -> bool {
75 self.empty 75 self.start == self.end && !self.full
76 } 76 }
77 77
78 #[allow(unused)] 78 #[allow(unused)]
79 pub fn len(&self) -> usize { 79 pub fn len(&self) -> usize {
80 if self.empty { 80 if self.is_empty() {
81 0 81 0
82 } else if self.start < self.end { 82 } else if self.start < self.end {
83 self.end - self.start 83 self.end - self.start
@@ -89,7 +89,7 @@ impl<const N: usize> RingBuffer<N> {
89 pub fn clear(&mut self) { 89 pub fn clear(&mut self) {
90 self.start = 0; 90 self.start = 0;
91 self.end = 0; 91 self.end = 0;
92 self.empty = true; 92 self.full = false;
93 } 93 }
94 94
95 fn wrap(&self, n: usize) -> usize { 95 fn wrap(&self, n: usize) -> usize {
diff --git a/embassy-sync/src/signal.rs b/embassy-sync/src/signal.rs
index bea67d8be..520f1a896 100644
--- a/embassy-sync/src/signal.rs
+++ b/embassy-sync/src/signal.rs
@@ -111,7 +111,21 @@ where
111 poll_fn(move |cx| self.poll_wait(cx)) 111 poll_fn(move |cx| self.poll_wait(cx))
112 } 112 }
113 113
114 /// non-blocking method to check whether this signal has been signaled. 114 /// non-blocking method to try and take the signal value.
115 pub fn try_take(&self) -> Option<T> {
116 self.state.lock(|cell| {
117 let state = cell.replace(State::None);
118 match state {
119 State::Signaled(res) => Some(res),
120 state => {
121 cell.set(state);
122 None
123 }
124 }
125 })
126 }
127
128 /// non-blocking method to check whether this signal has been signaled. This does not clear the signal.
115 pub fn signaled(&self) -> bool { 129 pub fn signaled(&self) -> bool {
116 self.state.lock(|cell| { 130 self.state.lock(|cell| {
117 let state = cell.replace(State::None); 131 let state = cell.replace(State::None);
diff --git a/embassy-sync/src/zerocopy_channel.rs b/embassy-sync/src/zerocopy_channel.rs
index f704cbd5d..cfce9a571 100644
--- a/embassy-sync/src/zerocopy_channel.rs
+++ b/embassy-sync/src/zerocopy_channel.rs
@@ -1,10 +1,7 @@
1//! A zero-copy queue for sending values between asynchronous tasks. 1//! A zero-copy queue for sending values between asynchronous tasks.
2//! 2//!
3//! It can be used concurrently by multiple producers (senders) and multiple 3//! It can be used concurrently by a producer (sender) and a
4//! consumers (receivers), i.e. it is an "MPMC channel". 4//! consumer (receiver), i.e. it is an "SPSC channel".
5//!
6//! Receivers are competing for messages. So a message that is received by
7//! one receiver is not received by any other.
8//! 5//!
9//! This queue takes a Mutex type so that various 6//! This queue takes a Mutex type so that various
10//! targets can be attained. For example, a ThreadModeMutex can be used 7//! targets can be attained. For example, a ThreadModeMutex can be used