Merge pull request #348 from embassy-rs/remove-portal

Remove Portal. Fixes #32
This commit is contained in:
Dario Nieuwenhuis 2021-08-05 22:31:06 +02:00 committed by GitHub
commit 36402b5487
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 0 additions and 122 deletions

View File

@ -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::*;

View File

@ -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() }
}
}