abi/
context.rs

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}