async_std/task/
task_locals_wrapper.rs1use std::cell::Cell;
2use std::ptr;
3
4use crate::task::{LocalsMap, Task, TaskId};
5use crate::utils::abort_on_panic;
6
7thread_local! {
8 static CURRENT: Cell<*const TaskLocalsWrapper> = Cell::new(ptr::null_mut());
10}
11
12pub(crate) struct TaskLocalsWrapper {
14 task: Task,
16
17 locals: LocalsMap,
19}
20
21impl TaskLocalsWrapper {
22 #[inline]
27 pub(crate) fn new(task: Task) -> Self {
28 Self {
29 task,
30 locals: LocalsMap::new(),
31 }
32 }
33
34 #[inline]
36 pub fn id(&self) -> TaskId {
37 self.task.id()
38 }
39
40 pub(crate) fn task(&self) -> &Task {
42 &self.task
43 }
44
45 pub(crate) fn locals(&self) -> &LocalsMap {
47 &self.locals
48 }
49
50 pub(crate) unsafe fn set_current<F, R>(task: *const TaskLocalsWrapper, f: F) -> R
52 where
53 F: FnOnce() -> R,
54 {
55 CURRENT.with(|current| {
56 let old_task = current.replace(task);
57 defer! {
58 current.set(old_task);
59 }
60 f()
61 })
62 }
63
64 pub(crate) fn get_current<F, R>(f: F) -> Option<R>
66 where
67 F: FnOnce(&TaskLocalsWrapper) -> R,
68 {
69 let res = CURRENT.try_with(|current| unsafe { current.get().as_ref().map(f) });
70 match res {
71 Ok(Some(val)) => Some(val),
72 Ok(None) | Err(_) => None,
73 }
74 }
75}
76
77impl Drop for TaskLocalsWrapper {
78 fn drop(&mut self) {
79 abort_on_panic(|| {
81 unsafe { self.locals.clear() };
82 });
83 }
84}