//! Thread local runtime context use crate::runtime::{Handle, TryCurrentError}; use std::cell::RefCell; thread_local! { static CONTEXT: RefCell> = RefCell::new(None) } pub(crate) fn try_current() -> Result { match CONTEXT.try_with(|ctx| ctx.borrow().clone()) { Ok(Some(handle)) => Ok(handle), Ok(None) => Err(TryCurrentError::new_no_context()), Err(_access_error) => Err(TryCurrentError::new_thread_local_destroyed()), } } pub(crate) fn current() -> Handle { match try_current() { Ok(handle) => handle, Err(e) => panic!("{}", e), } } cfg_io_driver! { pub(crate) fn io_handle() -> crate::runtime::driver::IoHandle { match CONTEXT.try_with(|ctx| { let ctx = ctx.borrow(); ctx.as_ref().expect(crate::util::error::CONTEXT_MISSING_ERROR).io_handle.clone() }) { Ok(io_handle) => io_handle, Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR), } } } cfg_signal_internal! { #[cfg(unix)] pub(crate) fn signal_handle() -> crate::runtime::driver::SignalHandle { match CONTEXT.try_with(|ctx| { let ctx = ctx.borrow(); ctx.as_ref().expect(crate::util::error::CONTEXT_MISSING_ERROR).signal_handle.clone() }) { Ok(signal_handle) => signal_handle, Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR), } } } cfg_time! { pub(crate) fn time_handle() -> crate::runtime::driver::TimeHandle { match CONTEXT.try_with(|ctx| { let ctx = ctx.borrow(); ctx.as_ref().expect(crate::util::error::CONTEXT_MISSING_ERROR).time_handle.clone() }) { Ok(time_handle) => time_handle, Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR), } } cfg_test_util! { pub(crate) fn clock() -> Option { match CONTEXT.try_with(|ctx| (*ctx.borrow()).as_ref().map(|ctx| ctx.clock.clone())) { Ok(clock) => clock, Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR), } } } } cfg_rt! { pub(crate) fn spawn_handle() -> Option { match CONTEXT.try_with(|ctx| (*ctx.borrow()).as_ref().map(|ctx| ctx.spawner.clone())) { Ok(spawner) => spawner, Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR), } } } /// Sets this [`Handle`] as the current active [`Handle`]. /// /// [`Handle`]: Handle pub(crate) fn enter(new: Handle) -> EnterGuard { match try_enter(new) { Some(guard) => guard, None => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR), } } /// Sets this [`Handle`] as the current active [`Handle`]. /// /// [`Handle`]: Handle pub(crate) fn try_enter(new: Handle) -> Option { CONTEXT .try_with(|ctx| { let old = ctx.borrow_mut().replace(new); EnterGuard(old) }) .ok() } #[derive(Debug)] pub(crate) struct EnterGuard(Option); impl Drop for EnterGuard { fn drop(&mut self) { CONTEXT.with(|ctx| { *ctx.borrow_mut() = self.0.take(); }); } }