1 //! Thread local runtime context
2 use crate::runtime::{Handle, TryCurrentError};
3
4 use std::cell::RefCell;
5
6 thread_local! {
7 static CONTEXT: RefCell<Option<Handle>> = RefCell::new(None)
8 }
9
try_current() -> Result<Handle, crate::runtime::TryCurrentError>10 pub(crate) fn try_current() -> Result<Handle, crate::runtime::TryCurrentError> {
11 match CONTEXT.try_with(|ctx| ctx.borrow().clone()) {
12 Ok(Some(handle)) => Ok(handle),
13 Ok(None) => Err(TryCurrentError::new_no_context()),
14 Err(_access_error) => Err(TryCurrentError::new_thread_local_destroyed()),
15 }
16 }
17
current() -> Handle18 pub(crate) fn current() -> Handle {
19 match try_current() {
20 Ok(handle) => handle,
21 Err(e) => panic!("{}", e),
22 }
23 }
24
25 cfg_io_driver! {
26 pub(crate) fn io_handle() -> crate::runtime::driver::IoHandle {
27 match CONTEXT.try_with(|ctx| {
28 let ctx = ctx.borrow();
29 ctx.as_ref().expect(crate::util::error::CONTEXT_MISSING_ERROR).io_handle.clone()
30 }) {
31 Ok(io_handle) => io_handle,
32 Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR),
33 }
34 }
35 }
36
37 cfg_signal_internal! {
38 #[cfg(unix)]
39 pub(crate) fn signal_handle() -> crate::runtime::driver::SignalHandle {
40 match CONTEXT.try_with(|ctx| {
41 let ctx = ctx.borrow();
42 ctx.as_ref().expect(crate::util::error::CONTEXT_MISSING_ERROR).signal_handle.clone()
43 }) {
44 Ok(signal_handle) => signal_handle,
45 Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR),
46 }
47 }
48 }
49
50 cfg_time! {
51 pub(crate) fn time_handle() -> crate::runtime::driver::TimeHandle {
52 match CONTEXT.try_with(|ctx| {
53 let ctx = ctx.borrow();
54 ctx.as_ref().expect(crate::util::error::CONTEXT_MISSING_ERROR).time_handle.clone()
55 }) {
56 Ok(time_handle) => time_handle,
57 Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR),
58 }
59 }
60
61 cfg_test_util! {
62 pub(crate) fn clock() -> Option<crate::runtime::driver::Clock> {
63 match CONTEXT.try_with(|ctx| (*ctx.borrow()).as_ref().map(|ctx| ctx.clock.clone())) {
64 Ok(clock) => clock,
65 Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR),
66 }
67 }
68 }
69 }
70
71 cfg_rt! {
72 pub(crate) fn spawn_handle() -> Option<crate::runtime::Spawner> {
73 match CONTEXT.try_with(|ctx| (*ctx.borrow()).as_ref().map(|ctx| ctx.spawner.clone())) {
74 Ok(spawner) => spawner,
75 Err(_) => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR),
76 }
77 }
78 }
79
80 /// Sets this [`Handle`] as the current active [`Handle`].
81 ///
82 /// [`Handle`]: Handle
enter(new: Handle) -> EnterGuard83 pub(crate) fn enter(new: Handle) -> EnterGuard {
84 match try_enter(new) {
85 Some(guard) => guard,
86 None => panic!("{}", crate::util::error::THREAD_LOCAL_DESTROYED_ERROR),
87 }
88 }
89
90 /// Sets this [`Handle`] as the current active [`Handle`].
91 ///
92 /// [`Handle`]: Handle
try_enter(new: Handle) -> Option<EnterGuard>93 pub(crate) fn try_enter(new: Handle) -> Option<EnterGuard> {
94 CONTEXT
95 .try_with(|ctx| {
96 let old = ctx.borrow_mut().replace(new);
97 EnterGuard(old)
98 })
99 .ok()
100 }
101
102 #[derive(Debug)]
103 pub(crate) struct EnterGuard(Option<Handle>);
104
105 impl Drop for EnterGuard {
drop(&mut self)106 fn drop(&mut self) {
107 CONTEXT.with(|ctx| {
108 *ctx.borrow_mut() = self.0.take();
109 });
110 }
111 }
112