aboutsummaryrefslogtreecommitdiff
path: root/embassy-util/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-08-22 14:12:13 +0000
committerGitHub <[email protected]>2022-08-22 14:12:13 +0000
commit381ac97746c318963b42eec6ced6773301c91519 (patch)
treeb1b3f644b77c6fcf4a0bbe2eabe19caba27c4c08 /embassy-util/src
parent1b9599025868d3a5d0d8e773593b05df8b2fecf2 (diff)
parent478f4727846f6a43c28fff3b09cb639c0b800465 (diff)
Merge #920
920: Remove Forever, switch to static_cell. r=Dirbaio a=Dirbaio Co-authored-by: Dario Nieuwenhuis <[email protected]>
Diffstat (limited to 'embassy-util/src')
-rw-r--r--embassy-util/src/channel/mpmc.rs10
-rw-r--r--embassy-util/src/forever.rs95
-rw-r--r--embassy-util/src/lib.rs2
-rw-r--r--embassy-util/src/pipe.rs6
4 files changed, 8 insertions, 105 deletions
diff --git a/embassy-util/src/channel/mpmc.rs b/embassy-util/src/channel/mpmc.rs
index 535f77e6f..263f29bfc 100644
--- a/embassy-util/src/channel/mpmc.rs
+++ b/embassy-util/src/channel/mpmc.rs
@@ -471,10 +471,10 @@ mod tests {
471 use futures_executor::ThreadPool; 471 use futures_executor::ThreadPool;
472 use futures_timer::Delay; 472 use futures_timer::Delay;
473 use futures_util::task::SpawnExt; 473 use futures_util::task::SpawnExt;
474 use static_cell::StaticCell;
474 475
475 use super::*; 476 use super::*;
476 use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; 477 use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
477 use crate::Forever;
478 478
479 fn capacity<T, const N: usize>(c: &ChannelState<T, N>) -> usize { 479 fn capacity<T, const N: usize>(c: &ChannelState<T, N>) -> usize {
480 c.queue.capacity() - c.queue.len() 480 c.queue.capacity() - c.queue.len()
@@ -549,8 +549,8 @@ mod tests {
549 async fn receiver_receives_given_try_send_async() { 549 async fn receiver_receives_given_try_send_async() {
550 let executor = ThreadPool::new().unwrap(); 550 let executor = ThreadPool::new().unwrap();
551 551
552 static CHANNEL: Forever<Channel<CriticalSectionRawMutex, u32, 3>> = Forever::new(); 552 static CHANNEL: StaticCell<Channel<CriticalSectionRawMutex, u32, 3>> = StaticCell::new();
553 let c = &*CHANNEL.put(Channel::new()); 553 let c = &*CHANNEL.init(Channel::new());
554 let c2 = c; 554 let c2 = c;
555 assert!(executor 555 assert!(executor
556 .spawn(async move { 556 .spawn(async move {
@@ -571,8 +571,8 @@ mod tests {
571 async fn senders_sends_wait_until_capacity() { 571 async fn senders_sends_wait_until_capacity() {
572 let executor = ThreadPool::new().unwrap(); 572 let executor = ThreadPool::new().unwrap();
573 573
574 static CHANNEL: Forever<Channel<CriticalSectionRawMutex, u32, 1>> = Forever::new(); 574 static CHANNEL: StaticCell<Channel<CriticalSectionRawMutex, u32, 1>> = StaticCell::new();
575 let c = &*CHANNEL.put(Channel::new()); 575 let c = &*CHANNEL.init(Channel::new());
576 assert!(c.try_send(1).is_ok()); 576 assert!(c.try_send(1).is_ok());
577 577
578 let c2 = c; 578 let c2 = c;
diff --git a/embassy-util/src/forever.rs b/embassy-util/src/forever.rs
deleted file mode 100644
index 4f3698211..000000000
--- a/embassy-util/src/forever.rs
+++ /dev/null
@@ -1,95 +0,0 @@
1use core::cell::UnsafeCell;
2use core::mem::MaybeUninit;
3
4use atomic_polyfill::{AtomicBool, Ordering};
5
6/// Type with static lifetime that may be written to once at runtime.
7///
8/// This may be used to initialize static objects at runtime, typically in the init routine.
9/// This is useful for objects such as Embassy's RTC, which cannot be initialized in a const
10/// context.
11///
12/// Note: IF a global mutable variable is desired, use a CriticalSectionMutex or ThreadModeMutex instead.
13///
14/// ```
15/// use embassy_util::Forever;
16/// // Using an integer for the sake of keeping this example self-contained,
17/// // see https://github.com/embassy-rs/embassy/wiki/Getting-Started for a more "proper" example.
18/// static SOME_INT: Forever<u32> =Forever::new();
19///
20/// // put returns a mutable pointer to the object stored in the forever, which may then be passed
21/// // around.
22/// let mut x = SOME_INT.put(42);
23/// assert_eq!(*x, 42);
24/// ```
25pub struct Forever<T> {
26 used: AtomicBool,
27 t: UnsafeCell<MaybeUninit<T>>,
28}
29
30unsafe impl<T> Send for Forever<T> {}
31unsafe impl<T> Sync for Forever<T> {}
32
33impl<T> Forever<T> {
34 /// Create a new `Forever`.
35 #[inline(always)]
36 pub const fn new() -> Self {
37 Self {
38 used: AtomicBool::new(false),
39 t: UnsafeCell::new(MaybeUninit::uninit()),
40 }
41 }
42
43 /// Store a value in this `Forever`, returning a mutable reference to it.
44 ///
45 /// Using this method, the compiler usually constructs `val` in the stack and then moves
46 /// it into the `Forever`. If `T` is big, this is likely to cause stack overflows.
47 /// Considering using [`Signal::put_with`] instead, which will construct it in-place inside the `Forever`.
48 ///
49 /// # Panics
50 ///
51 /// Panics if this `Forever` already has a value stored in it.
52 #[inline(always)]
53 #[allow(clippy::mut_from_ref)]
54 pub fn put(&'static self, val: T) -> &'static mut T {
55 self.put_with(|| val)
56 }
57
58 /// Store the closure return value in this `Forever`, returning a mutable reference to it.
59 ///
60 /// The advantage over [`Forever::put`] is that this method allows the closure to construct
61 /// the `T` value in-place directly inside the `Forever`, saving stack space.
62 ///
63 /// # Panics
64 ///
65 /// Panics if this `Forever` already has a value stored in it.
66 #[inline(always)]
67 #[allow(clippy::mut_from_ref)]
68 pub fn put_with(&'static self, val: impl FnOnce() -> T) -> &'static mut T {
69 if self
70 .used
71 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
72 .is_err()
73 {
74 panic!("Forever.put() called multiple times");
75 }
76
77 let p: &'static mut MaybeUninit<T> = unsafe { &mut *self.t.get() };
78 p.write(val())
79 }
80
81 /// Unsafely get a mutable reference to the contents of this Forever.
82 ///
83 /// # Safety
84 ///
85 /// This is undefined behavior if:
86 ///
87 /// - The `Forever` has not been initialized yet (with `put' or `put_with`), or
88 /// - A reference to the contents (mutable or not) already exists.
89 #[inline(always)]
90 #[allow(clippy::mut_from_ref)]
91 pub unsafe fn steal(&self) -> &mut T {
92 let p: &mut MaybeUninit<T> = &mut *self.t.get();
93 p.assume_init_mut()
94 }
95}
diff --git a/embassy-util/src/lib.rs b/embassy-util/src/lib.rs
index 110c72811..8ec3300d9 100644
--- a/embassy-util/src/lib.rs
+++ b/embassy-util/src/lib.rs
@@ -16,10 +16,8 @@ pub mod mutex;
16pub mod pipe; 16pub mod pipe;
17pub mod waitqueue; 17pub mod waitqueue;
18 18
19mod forever;
20mod select; 19mod select;
21mod yield_now; 20mod yield_now;
22 21
23pub use forever::*;
24pub use select::*; 22pub use select::*;
25pub use yield_now::*; 23pub use yield_now::*;
diff --git a/embassy-util/src/pipe.rs b/embassy-util/src/pipe.rs
index 9c20aeeff..d85b843e4 100644
--- a/embassy-util/src/pipe.rs
+++ b/embassy-util/src/pipe.rs
@@ -461,10 +461,10 @@ mod io_impls {
461mod tests { 461mod tests {
462 use futures_executor::ThreadPool; 462 use futures_executor::ThreadPool;
463 use futures_util::task::SpawnExt; 463 use futures_util::task::SpawnExt;
464 use static_cell::StaticCell;
464 465
465 use super::*; 466 use super::*;
466 use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; 467 use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
467 use crate::Forever;
468 468
469 fn capacity<const N: usize>(c: &PipeState<N>) -> usize { 469 fn capacity<const N: usize>(c: &PipeState<N>) -> usize {
470 N - c.buffer.len() 470 N - c.buffer.len()
@@ -528,8 +528,8 @@ mod tests {
528 async fn receiver_receives_given_try_write_async() { 528 async fn receiver_receives_given_try_write_async() {
529 let executor = ThreadPool::new().unwrap(); 529 let executor = ThreadPool::new().unwrap();
530 530
531 static CHANNEL: Forever<Pipe<CriticalSectionRawMutex, 3>> = Forever::new(); 531 static CHANNEL: StaticCell<Pipe<CriticalSectionRawMutex, 3>> = StaticCell::new();
532 let c = &*CHANNEL.put(Pipe::new()); 532 let c = &*CHANNEL.init(Pipe::new());
533 let c2 = c; 533 let c2 = c;
534 let f = async move { 534 let f = async move {
535 assert_eq!(c2.try_write(&[42]), Ok(1)); 535 assert_eq!(c2.try_write(&[42]), Ok(1));