Skip to main content

SyncUnsafeCell

Struct SyncUnsafeCell 

Source
pub struct SyncUnsafeCell<T>(/* private fields */);
Expand description

Thread-safe wrapper for UnsafeCell usable in static contexts.

SyncUnsafeCell<T> is a thin wrapper around UnsafeCell<T> that manually implements the Sync and Send traits, allowing its use in static variables. This is necessary in Rust 2024+ where static mut is no longer allowed.

§Safety

The manual implementation of Sync and Send is unsafe because the compiler cannot verify that concurrent access is safe. It is the programmer’s responsibility to ensure that:

  1. In single-threaded environments (e.g., embedded bare-metal), there are no synchronization issues since only one thread of execution exists.

  2. In multi-threaded environments, access to SyncUnsafeCell must be externally protected via mutexes, critical sections, or other synchronization primitives.

  3. No data race conditions occur during data access.

§Typical Usage

This structure is designed to replace static mut in embedded scenarios where global mutability is necessary (e.g., hardware registers, shared buffers).

§Examples

use osal_rs::utils::SyncUnsafeCell;

// Global mutable variable in Rust 2024+
static COUNTER: SyncUnsafeCell<u32> = SyncUnsafeCell::new(0);

fn increment_counter() {
    unsafe {
        let counter = &mut *COUNTER.get();
        *counter += 1;
    }
}

§Alternatives

For non-embedded code or when real synchronization is needed:

  • Use Mutex<T> or RwLock<T> for thread-safe protection
  • Use AtomicUsize, AtomicBool, etc. for simple atomic types

Implementations§

Source§

impl<T> SyncUnsafeCell<T>

Source

pub const fn new(value: T) -> Self

Creates a new instance of SyncUnsafeCell<T>.

This is a const function, allowing initialization in static and constant contexts.

§Parameters
  • value - The initial value to wrap
§Examples
use osal_rs::utils::SyncUnsafeCell;

static CONFIG: SyncUnsafeCell<u32> = SyncUnsafeCell::new(42);
Source

pub unsafe fn get(&self) -> *mut T

Gets a raw mutable pointer to the contained value.

§Safety

This function is unsafe because:

  • It returns a raw pointer that bypasses the borrow checker
  • The caller must ensure there are no mutable aliases
  • Dereferencing the pointer without synchronization can cause data races
§Returns

A raw mutable pointer *mut T to the inner value.

§Examples
use osal_rs::utils::SyncUnsafeCell;

static VALUE: SyncUnsafeCell<i32> = SyncUnsafeCell::new(0);

unsafe {
    let ptr = VALUE.get();
    *ptr = 42;
}

Trait Implementations§

Source§

impl<T> Send for SyncUnsafeCell<T>

Manual implementation of Send for SyncUnsafeCell<T>.

§Safety

This is unsafe because it asserts that SyncUnsafeCell<T> can be transferred between threads. The inner type T may not be Send, so the caller must handle memory safety.

Source§

impl<T> Sync for SyncUnsafeCell<T>

Manual implementation of Sync for SyncUnsafeCell<T>.

§Safety

This is unsafe because it asserts that SyncUnsafeCell<T> can be shared between threads without causing data races. The caller must ensure synchronization.

Auto Trait Implementations§

§

impl<T> !Freeze for SyncUnsafeCell<T>

§

impl<T> !RefUnwindSafe for SyncUnsafeCell<T>

§

impl<T> Unpin for SyncUnsafeCell<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for SyncUnsafeCell<T>
where T: UnsafeUnpin,

§

impl<T> UnwindSafe for SyncUnsafeCell<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.