// Copyright 2025 Jonas Kruckenberg // // Licensed under the Apache License, Version 2.0, or the MIT license , at your option. This file may not be // copied, modified, or distributed except according to those terms. use alloc::boxed::Box; use core::ptr; use core::sync::atomic::{AtomicPtr, Ordering}; pub(crate) struct AtomicCell { data: AtomicPtr, } // Safety: `AtomicCell` uses atomic swaps, so as long as the data is Send `AtomicCell` is Send unsafe impl Send for AtomicCell {} // Safety: `AtomicCell` uses atomic swaps, so as long as the data is Send `AtomicCell` is Sync unsafe impl Sync for AtomicCell {} impl AtomicCell { pub(crate) fn new(data: Option>) -> AtomicCell { AtomicCell { data: AtomicPtr::new(to_raw(data)), } } pub(crate) fn swap(&self, val: Option>) -> Option> { let old = self.data.swap(to_raw(val), Ordering::AcqRel); from_raw(old) } pub(crate) fn set(&self, val: Box) { let _ = self.swap(Some(val)); } pub(crate) fn take(&self) -> Option> { self.swap(None) } } fn to_raw(data: Option>) -> *mut T { data.map_or(ptr::null_mut(), Box::into_raw) } fn from_raw(val: *mut T) -> Option> { if val.is_null() { None } else { // Safety: `from_raw` is only called on pointers created using `to_raw` which are correctly // boxed pointers Some(unsafe { Box::from_raw(val) }) } } impl Drop for AtomicCell { fn drop(&mut self) { // Free any data still held by the cell let _ = self.take(); } }