mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-26 16:52:33 +00:00
Merge pull request #348 from embassy-rs/remove-portal
Remove Portal. Fixes #32
This commit is contained in:
commit
36402b5487
@ -3,7 +3,6 @@ mod drop_bomb;
|
||||
mod forever;
|
||||
mod mutex;
|
||||
mod on_drop;
|
||||
mod portal;
|
||||
mod signal;
|
||||
|
||||
#[cfg_attr(feature = "executor-agnostic", path = "waker_agnostic.rs")]
|
||||
@ -14,7 +13,6 @@ pub use forever::*;
|
||||
pub mod mpsc;
|
||||
pub use mutex::*;
|
||||
pub use on_drop::*;
|
||||
pub use portal::*;
|
||||
pub use signal::*;
|
||||
pub use waker::*;
|
||||
|
||||
|
@ -1,120 +0,0 @@
|
||||
use core::cell::UnsafeCell;
|
||||
use core::mem;
|
||||
use core::mem::MaybeUninit;
|
||||
|
||||
use crate::util::*;
|
||||
|
||||
/// Utility to call a closure across tasks.
|
||||
pub struct Portal<T> {
|
||||
state: UnsafeCell<State<T>>,
|
||||
}
|
||||
|
||||
enum State<T> {
|
||||
None,
|
||||
Running,
|
||||
Waiting(*mut dyn FnMut(T)),
|
||||
}
|
||||
|
||||
impl<T> Portal<T> {
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
state: UnsafeCell::new(State::None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call(&self, val: T) {
|
||||
unsafe {
|
||||
match *self.state.get() {
|
||||
State::None => {}
|
||||
State::Running => panic!("Portall::call() called reentrantly"),
|
||||
State::Waiting(func) => (*func)(val),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait_once<'a, R, F>(&'a self, mut func: F) -> R
|
||||
where
|
||||
F: FnMut(T) -> R + 'a,
|
||||
{
|
||||
let bomb = DropBomb::new();
|
||||
|
||||
let signal = Signal::new();
|
||||
let mut result: MaybeUninit<R> = MaybeUninit::uninit();
|
||||
let mut call_func = |val: T| {
|
||||
unsafe {
|
||||
let state = &mut *self.state.get();
|
||||
*state = State::None;
|
||||
result.as_mut_ptr().write(func(val))
|
||||
};
|
||||
signal.signal(());
|
||||
};
|
||||
|
||||
let func_ptr: *mut dyn FnMut(T) = &mut call_func as _;
|
||||
let func_ptr: *mut dyn FnMut(T) = unsafe { mem::transmute(func_ptr) };
|
||||
|
||||
unsafe {
|
||||
let state = &mut *self.state.get();
|
||||
match state {
|
||||
State::None => {}
|
||||
_ => panic!("Multiple tasks waiting on same portal"),
|
||||
}
|
||||
*state = State::Waiting(func_ptr);
|
||||
}
|
||||
|
||||
signal.wait().await;
|
||||
|
||||
bomb.defuse();
|
||||
|
||||
unsafe { result.assume_init() }
|
||||
}
|
||||
|
||||
pub async fn wait_many<'a, R, F>(&'a self, mut func: F) -> R
|
||||
where
|
||||
F: FnMut(T) -> Option<R> + 'a,
|
||||
{
|
||||
let bomb = DropBomb::new();
|
||||
|
||||
let signal = Signal::new();
|
||||
let mut result: MaybeUninit<R> = MaybeUninit::uninit();
|
||||
let mut call_func = |val: T| {
|
||||
unsafe {
|
||||
let state = &mut *self.state.get();
|
||||
|
||||
let func_ptr = match *state {
|
||||
State::Waiting(p) => p,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// Set state to Running while running the function to avoid reentrancy.
|
||||
*state = State::Running;
|
||||
|
||||
*state = match func(val) {
|
||||
None => State::Waiting(func_ptr),
|
||||
Some(res) => {
|
||||
result.as_mut_ptr().write(res);
|
||||
signal.signal(());
|
||||
State::None
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
let func_ptr: *mut dyn FnMut(T) = &mut call_func as _;
|
||||
let func_ptr: *mut dyn FnMut(T) = unsafe { mem::transmute(func_ptr) };
|
||||
|
||||
unsafe {
|
||||
let state = &mut *self.state.get();
|
||||
match *state {
|
||||
State::None => {}
|
||||
_ => panic!("Multiple tasks waiting on same portal"),
|
||||
}
|
||||
*state = State::Waiting(func_ptr);
|
||||
}
|
||||
|
||||
signal.wait().await;
|
||||
|
||||
bomb.defuse();
|
||||
|
||||
unsafe { result.assume_init() }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user