1use futures::block_on;
2use synchronization::{blocking_mutex::raw::CriticalSectionRawMutex, rwlock::RwLock};
3use task::TaskIdentifier;
4
5pub static CONTEXT: Context = Context::new();
6
7pub fn get_instance() -> &'static Context {
8 &CONTEXT
9}
10
11struct Inner {
12 task: Option<TaskIdentifier>,
13}
14
15pub struct Context(RwLock<CriticalSectionRawMutex, Inner>);
16
17impl Default for Context {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23impl Context {
24 pub const fn new() -> Self {
25 Self(RwLock::new(Inner { task: None }))
26 }
27
28 pub fn get_current_task_identifier(&self) -> TaskIdentifier {
29 block_on(self.0.read()).task.expect("No current task set")
30 }
31
32 pub async fn set_task(&self, task: TaskIdentifier) {
33 loop {
34 let mut inner = self.0.write().await;
35
36 if inner.task.is_none() {
37 inner.task.replace(task);
38 break;
39 }
40 }
41 }
42
43 pub async fn clear_task(&self) {
44 let mut inner = self.0.write().await;
45 inner.task.take();
46 }
47
48 pub async fn call_abi<F, Fut, R>(&self, function: F) -> R
49 where
50 F: FnOnce() -> Fut,
51 Fut: core::future::Future<Output = R>,
52 {
53 let task = task::get_instance().get_current_task_identifier().await;
54 self.set_task(task).await;
55 let result = function().await;
56 self.clear_task().await;
57 result
58 }
59}