Skip to main content

async_local_executor/
tls.rs

1use crate::executor::Executor;
2use std::cell::Cell;
3use std::marker::PhantomData;
4use std::ops::{Deref, DerefMut};
5use std::{mem, ptr};
6
7thread_local! {
8     static EXECUTOR: Cell<Option<&'static mut Executor>> = const { Cell::new(None) };
9}
10
11#[must_use = "deref in order to access the executor"]
12#[derive(Debug)]
13pub struct ExecutorGuard {
14    executor: &'static mut Executor,
15}
16
17impl Drop for ExecutorGuard {
18    fn drop(&mut self) {
19        let executor = unsafe { ptr::read(&raw const self.executor) };
20        EXECUTOR.set(Some(executor));
21    }
22}
23
24impl Deref for ExecutorGuard {
25    type Target = Executor;
26
27    fn deref(&self) -> &Self::Target {
28        self.executor
29    }
30}
31
32impl DerefMut for ExecutorGuard {
33    fn deref_mut(&mut self) -> &mut Self::Target {
34        self.executor
35    }
36}
37
38pub fn try_executor() -> Option<ExecutorGuard> {
39    Some(ExecutorGuard {
40        executor: EXECUTOR.try_with(Cell::take).ok()??,
41    })
42}
43
44#[cold]
45const fn no_executor<T>() -> T {
46    panic!("no executor present");
47}
48
49pub fn executor() -> ExecutorGuard {
50    try_executor().unwrap_or_else(no_executor)
51}
52
53pub struct EnterGuard<'a> {
54    marker: PhantomData<&'a mut Executor>,
55}
56
57impl Drop for EnterGuard<'_> {
58    fn drop(&mut self) {
59        let _ = EXECUTOR.try_with(Cell::take);
60    }
61}
62
63impl Executor {
64    #[inline]
65    pub fn enter(&mut self) -> EnterGuard<'_> {
66        let prev = EXECUTOR.replace(Some(unsafe { mem::transmute(self) }));
67        assert!(prev.is_none(), "there can only be one executor present");
68        EnterGuard {
69            marker: PhantomData,
70        }
71    }
72
73    #[inline]
74    pub fn run_in<O, F: FnOnce() -> O>(&mut self, fun: F) -> O {
75        let guard = self.enter();
76        let ret = fun();
77        drop(guard);
78        ret
79    }
80}