embedded_threadsafe/safecells/
shared.rs

1//! A cell that can be safely be shared across thread boundaries and interrupt contexts
2
3use crate::{runtime, LazyCell};
4use core::{
5    cell::UnsafeCell,
6    fmt::{self, Debug, Formatter},
7};
8
9/// A cell that can be safely be shared across thread boundaries and interrupt contexts
10pub struct SharedCell<T> {
11    /// The wrapped value
12    inner: UnsafeCell<T>,
13}
14impl<T> SharedCell<T> {
15    /// Creates a new cell
16    pub const fn new(value: T) -> Self {
17        Self { inner: UnsafeCell::new(value) }
18    }
19
20    /// Provides scoped access to the underlying value
21    pub fn scope<F, FR>(&self, scope: F) -> FR
22    where
23        F: FnOnce(&mut T) -> FR,
24    {
25        // Create mutable slots to transfer state to/from the closure and create the caller
26        let mut scope = Some(scope);
27        let mut result: Option<FR> = None;
28        let mut call_scope = || {
29            // Consume and call the scope
30            let scope = scope.take().expect("missing scope function");
31            let result_ = unsafe { self.raw(scope) };
32            result = Some(result_);
33        };
34
35        // Run the implementation in a threadsafe context and return the result
36        unsafe { runtime::_runtime_threadsafe_e0LtH0x3(&mut call_scope) };
37        result.expect("implementation scope did not set result value")
38    }
39
40    /// Provides an unsafe raw scoped access to the underlying value
41    ///
42    /// # Safety
43    /// This function provides unchecked, mutable access to the underlying value, so incorrect use of this function may
44    /// lead to race conditions or undefined behavior.
45    pub unsafe fn raw<F, FR>(&self, scope: F) -> FR
46    where
47        F: FnOnce(&mut T) -> FR,
48    {
49        // Provide access to the inner value
50        let inner_ptr = self.inner.get();
51        let value = inner_ptr.as_mut().expect("unexpected NULL pointer inside cell");
52        scope(value)
53    }
54}
55impl<T> SharedCell<LazyCell<T>> {
56    /// Provides scoped access to the underlying lazy cell
57    ///
58    /// # Panic
59    /// This function will panic if called from another thread or interrupt context
60    pub fn lazy_scope<F, FR>(&self, scope: F) -> FR
61    where
62        F: FnOnce(&mut T) -> FR,
63    {
64        self.scope(|lazy| lazy.scope_mut(scope))
65    }
66}
67impl<T> Debug for SharedCell<T>
68where
69    T: Debug,
70{
71    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
72        self.scope(|value| value.fmt(f))
73    }
74}
75unsafe impl<T> Sync for SharedCell<T>
76where
77    T: Send,
78{
79    // Marker trait, no members to implement
80}