Next Generation WASM Microkernel Operating System
1// Copyright 2025 Jonas Kruckenberg
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use alloc::boxed::Box;
9use core::ptr;
10use core::sync::atomic::{AtomicPtr, Ordering};
11
12pub(crate) struct AtomicCell<T> {
13 data: AtomicPtr<T>,
14}
15
16// Safety: `AtomicCell` uses atomic swaps, so as long as the data is Send `AtomicCell` is Send
17unsafe impl<T: Send> Send for AtomicCell<T> {}
18// Safety: `AtomicCell` uses atomic swaps, so as long as the data is Send `AtomicCell` is Sync
19unsafe impl<T: Send> Sync for AtomicCell<T> {}
20
21impl<T> AtomicCell<T> {
22 pub(crate) fn new(data: Option<Box<T>>) -> AtomicCell<T> {
23 AtomicCell {
24 data: AtomicPtr::new(to_raw(data)),
25 }
26 }
27
28 pub(crate) fn swap(&self, val: Option<Box<T>>) -> Option<Box<T>> {
29 let old = self.data.swap(to_raw(val), Ordering::AcqRel);
30 from_raw(old)
31 }
32
33 pub(crate) fn set(&self, val: Box<T>) {
34 let _ = self.swap(Some(val));
35 }
36
37 pub(crate) fn take(&self) -> Option<Box<T>> {
38 self.swap(None)
39 }
40}
41
42fn to_raw<T>(data: Option<Box<T>>) -> *mut T {
43 data.map_or(ptr::null_mut(), Box::into_raw)
44}
45
46fn from_raw<T>(val: *mut T) -> Option<Box<T>> {
47 if val.is_null() {
48 None
49 } else {
50 // Safety: `from_raw` is only called on pointers created using `to_raw` which are correctly
51 // boxed pointers
52 Some(unsafe { Box::from_raw(val) })
53 }
54}
55
56impl<T> Drop for AtomicCell<T> {
57 fn drop(&mut self) {
58 // Free any data still held by the cell
59 let _ = self.take();
60 }
61}