aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy/src/util/mod.rs2
-rw-r--r--embassy/src/util/portal.rs120
2 files changed, 0 insertions, 122 deletions
diff --git a/embassy/src/util/mod.rs b/embassy/src/util/mod.rs
index 87d313e28..e66576b33 100644
--- a/embassy/src/util/mod.rs
+++ b/embassy/src/util/mod.rs
@@ -3,7 +3,6 @@ mod drop_bomb;
3mod forever; 3mod forever;
4mod mutex; 4mod mutex;
5mod on_drop; 5mod on_drop;
6mod portal;
7mod signal; 6mod signal;
8 7
9#[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")] 8#[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")]
@@ -14,7 +13,6 @@ pub use forever::*;
14pub mod mpsc; 13pub mod mpsc;
15pub use mutex::*; 14pub use mutex::*;
16pub use on_drop::*; 15pub use on_drop::*;
17pub use portal::*;
18pub use signal::*; 16pub use signal::*;
19pub use waker::*; 17pub use waker::*;
20 18
diff --git a/embassy/src/util/portal.rs b/embassy/src/util/portal.rs
deleted file mode 100644
index 8ea481093..000000000
--- a/embassy/src/util/portal.rs
+++ /dev/null
@@ -1,120 +0,0 @@
1use core::cell::UnsafeCell;
2use core::mem;
3use core::mem::MaybeUninit;
4
5use crate::util::*;
6
7/// Utility to call a closure across tasks.
8pub struct Portal<T> {
9 state: UnsafeCell<State<T>>,
10}
11
12enum State<T> {
13 None,
14 Running,
15 Waiting(*mut dyn FnMut(T)),
16}
17
18impl<T> Portal<T> {
19 pub const fn new() -> Self {
20 Self {
21 state: UnsafeCell::new(State::None),
22 }
23 }
24
25 pub fn call(&self, val: T) {
26 unsafe {
27 match *self.state.get() {
28 State::None => {}
29 State::Running => panic!("Portall::call() called reentrantly"),
30 State::Waiting(func) => (*func)(val),
31 }
32 }
33 }
34
35 pub async fn wait_once<'a, R, F>(&'a self, mut func: F) -> R
36 where
37 F: FnMut(T) -> R + 'a,
38 {
39 let bomb = DropBomb::new();
40
41 let signal = Signal::new();
42 let mut result: MaybeUninit<R> = MaybeUninit::uninit();
43 let mut call_func = |val: T| {
44 unsafe {
45 let state = &mut *self.state.get();
46 *state = State::None;
47 result.as_mut_ptr().write(func(val))
48 };
49 signal.signal(());
50 };
51
52 let func_ptr: *mut dyn FnMut(T) = &mut call_func as _;
53 let func_ptr: *mut dyn FnMut(T) = unsafe { mem::transmute(func_ptr) };
54
55 unsafe {
56 let state = &mut *self.state.get();
57 match state {
58 State::None => {}
59 _ => panic!("Multiple tasks waiting on same portal"),
60 }
61 *state = State::Waiting(func_ptr);
62 }
63
64 signal.wait().await;
65
66 bomb.defuse();
67
68 unsafe { result.assume_init() }
69 }
70
71 pub async fn wait_many<'a, R, F>(&'a self, mut func: F) -> R
72 where
73 F: FnMut(T) -> Option<R> + 'a,
74 {
75 let bomb = DropBomb::new();
76
77 let signal = Signal::new();
78 let mut result: MaybeUninit<R> = MaybeUninit::uninit();
79 let mut call_func = |val: T| {
80 unsafe {
81 let state = &mut *self.state.get();
82
83 let func_ptr = match *state {
84 State::Waiting(p) => p,
85 _ => unreachable!(),
86 };
87
88 // Set state to Running while running the function to avoid reentrancy.
89 *state = State::Running;
90
91 *state = match func(val) {
92 None => State::Waiting(func_ptr),
93 Some(res) => {
94 result.as_mut_ptr().write(res);
95 signal.signal(());
96 State::None
97 }
98 };
99 };
100 };
101
102 let func_ptr: *mut dyn FnMut(T) = &mut call_func as _;
103 let func_ptr: *mut dyn FnMut(T) = unsafe { mem::transmute(func_ptr) };
104
105 unsafe {
106 let state = &mut *self.state.get();
107 match *state {
108 State::None => {}
109 _ => panic!("Multiple tasks waiting on same portal"),
110 }
111 *state = State::Waiting(func_ptr);
112 }
113
114 signal.wait().await;
115
116 bomb.defuse();
117
118 unsafe { result.assume_init() }
119 }
120}