embedded_threadsafe/safecells/
interrupt.rs1use crate::{runtime, LazyCell};
4use core::{
5 cell::UnsafeCell,
6 fmt::{self, Debug, Formatter},
7};
8
9pub struct InterruptCell<T> {
14 inner: UnsafeCell<T>,
16 thread_id: usize,
18}
19impl<T> InterruptCell<T> {
20 pub const fn new_with_threadid(value: T, thread_id: usize) -> Self {
22 Self { inner: UnsafeCell::new(value), thread_id }
23 }
24
25 pub fn new(value: T) -> Self {
27 let thread_id = unsafe { runtime::_runtime_threadid_ZhZIZBv4() };
29 Self::new_with_threadid(value, thread_id)
30 }
31
32 pub fn scope<F, FR>(&self, scope: F) -> FR
37 where
38 F: FnOnce(&mut T) -> FR,
39 {
40 let thread_id = unsafe { runtime::_runtime_threadid_ZhZIZBv4() };
42 assert_eq!(thread_id, self.thread_id, "cannot access local cell from another thread");
43
44 let mut scope = Some(scope);
46 let mut result: Option<FR> = None;
47 let mut call_scope = || {
48 let scope = scope.take().expect("missing scope function");
50 let result_ = unsafe { self.raw(scope) };
51 result = Some(result_);
52 };
53
54 unsafe { runtime::_runtime_interruptsafe_1l52Ge5e(&mut call_scope) };
56 result.expect("implementation scope did not set result value")
57 }
58
59 pub unsafe fn raw<F, FR>(&self, scope: F) -> FR
65 where
66 F: FnOnce(&mut T) -> FR,
67 {
68 let inner_ptr = self.inner.get();
70 let value = inner_ptr.as_mut().expect("unexpected NULL pointer inside cell");
71 scope(value)
72 }
73}
74impl<T> InterruptCell<LazyCell<T>> {
75 pub fn lazy_scope<F, FR>(&self, scope: F) -> FR
80 where
81 F: FnOnce(&mut T) -> FR,
82 {
83 self.scope(|lazy| lazy.scope_mut(scope))
84 }
85}
86impl<T> Debug for InterruptCell<T>
87where
88 T: Debug,
89{
90 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
91 let thread_id = unsafe { runtime::_runtime_threadid_ZhZIZBv4() };
93 if thread_id != self.thread_id {
94 return f.debug_tuple("InterruptCell").field(&"<opaque due to different thread>").finish();
95 }
96
97 self.scope(|value| value.fmt(f))
99 }
100}
101unsafe impl<T> Sync for InterruptCell<T>
102where
103 T: Send,
104{
105 }