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