use futures_executor::Enter;
use std::cell::RefCell;
use std::thread::LocalKey;
struct Reset<T: 'static> {
current: &'static LocalKey<Current<T>>,
}
impl<T> Drop for Reset<T> {
fn drop(&mut self) {
let _ = self.current.try_with(|c| *c.inner.borrow_mut() = None);
}
}
#[derive(Debug)]
pub struct Current<T> {
inner: RefCell<Option<T>>,
}
impl<T> Current<T> {
pub const fn new() -> Self {
Self {
inner: RefCell::new(None),
}
}
#[inline]
pub fn enter<F, R>(this: &'static LocalKey<Self>, enter: &mut Enter, value: T, f: F) -> R
where
F: FnOnce(&mut Enter) -> R,
{
this.with(|c| {
{
let mut inner = c.inner.borrow_mut();
assert!(inner.is_none(), "can't enter more than once at a time");
*inner = Some(value);
}
let _reset = Reset { current: this };
f(enter)
})
}
#[inline]
pub fn with<F, R>(this: &'static LocalKey<Self>, f: F) -> R
where
F: FnOnce(Option<&T>) -> R,
{
this.with(|c| {
f(c.inner.borrow().as_ref())
})
}
#[inline]
pub fn with_mut<F, R>(this: &'static LocalKey<Self>, f: F) -> R
where
F: FnOnce(Option<&mut T>) -> R,
{
this.with(|c| {
f(c.inner.borrow_mut().as_mut())
})
}
}