// SPDX-License-Identifier: GPL-2.012// Copyright (C) 2024 Google LLC.34//! A field that is exclusively owned by a [`ListArc`].5//!6//! This can be used to have reference counted struct where one of the reference counted pointers7//! has exclusive access to a field of the struct.8//!9//! [`ListArc`]: crate::list::ListArc1011use core::cell::UnsafeCell;1213/// A field owned by a specific [`ListArc`].14///15/// [`ListArc`]: crate::list::ListArc16pub struct ListArcField<T, const ID: u64 = 0> {17value: UnsafeCell<T>,18}1920// SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.21unsafe impl<T: Send + Sync, const ID: u64> Send for ListArcField<T, ID> {}22// SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.23unsafe impl<T: Send + Sync, const ID: u64> Sync for ListArcField<T, ID> {}2425impl<T, const ID: u64> ListArcField<T, ID> {26/// Creates a new `ListArcField`.27pub fn new(value: T) -> Self {28Self {29value: UnsafeCell::new(value),30}31}3233/// Access the value when we have exclusive access to the `ListArcField`.34///35/// This allows access to the field using an `UniqueArc` instead of a `ListArc`.36pub fn get_mut(&mut self) -> &mut T {37self.value.get_mut()38}3940/// Unsafely assert that you have shared access to the `ListArc` for this field.41///42/// # Safety43///44/// The caller must have shared access to the `ListArc<ID>` containing the struct with this45/// field for the duration of the returned reference.46pub unsafe fn assert_ref(&self) -> &T {47// SAFETY: The caller has shared access to the `ListArc`, so they also have shared access48// to this field.49unsafe { &*self.value.get() }50}5152/// Unsafely assert that you have mutable access to the `ListArc` for this field.53///54/// # Safety55///56/// The caller must have mutable access to the `ListArc<ID>` containing the struct with this57/// field for the duration of the returned reference.58#[expect(clippy::mut_from_ref)]59pub unsafe fn assert_mut(&self) -> &mut T {60// SAFETY: The caller has exclusive access to the `ListArc`, so they also have exclusive61// access to this field.62unsafe { &mut *self.value.get() }63}64}6566/// Defines getters for a [`ListArcField`].67#[macro_export]68macro_rules! define_list_arc_field_getter {69($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident }70$($rest:tt)*71) => {72$pub fn $name<'a>(self: &'a $crate::list::ListArc<Self $(, $id)?>) -> &'a $typ {73let field = &(&**self).$field;74// SAFETY: We have a shared reference to the `ListArc`.75unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_ref(field) }76}7778$crate::list::define_list_arc_field_getter!($($rest)*);79};8081($pub:vis fn $name:ident(&mut self $(<$id:tt>)?) -> &mut $typ:ty { $field:ident }82$($rest:tt)*83) => {84$pub fn $name<'a>(self: &'a mut $crate::list::ListArc<Self $(, $id)?>) -> &'a mut $typ {85let field = &(&**self).$field;86// SAFETY: We have a mutable reference to the `ListArc`.87unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_mut(field) }88}8990$crate::list::define_list_arc_field_getter!($($rest)*);91};9293() => {};94}95pub use define_list_arc_field_getter;969798