97 lines · 3.4 KB · Rust
RawDownload
// SPDX-License-Identifier: GPL-2.0 // Copyright (C) 2024 Google LLC. //! A field that is exclusively owned by a [`ListArc`].//!//! This can be used to have reference counted struct where one of the reference counted pointers//! has exclusive access to a field of the struct.//!//! [`ListArc`]: crate::list::ListArc use core::cell::UnsafeCell; /// A field owned by a specific [`ListArc`].////// [`ListArc`]: crate::list::ListArcpub struct ListArcField<T, const ID: u64 = 0> {    value: UnsafeCell<T>,} // SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.unsafe impl<T: Send + Sync, const ID: u64> Send for ListArcField<T, ID> {}// SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.unsafe impl<T: Send + Sync, const ID: u64> Sync for ListArcField<T, ID> {} impl<T, const ID: u64> ListArcField<T, ID> {    /// Creates a new `ListArcField`.    pub fn new(value: T) -> Self {        Self {            value: UnsafeCell::new(value),        }    }     /// Access the value when we have exclusive access to the `ListArcField`.    ///    /// This allows access to the field using an `UniqueArc` instead of a `ListArc`.    pub fn get_mut(&mut self) -> &mut T {        self.value.get_mut()    }     /// Unsafely assert that you have shared access to the `ListArc` for this field.    ///    /// # Safety    ///    /// The caller must have shared access to the `ListArc<ID>` containing the struct with this    /// field for the duration of the returned reference.    pub unsafe fn assert_ref(&self) -> &T {        // SAFETY: The caller has shared access to the `ListArc`, so they also have shared access        // to this field.        unsafe { &*self.value.get() }    }     /// Unsafely assert that you have mutable access to the `ListArc` for this field.    ///    /// # Safety    ///    /// The caller must have mutable access to the `ListArc<ID>` containing the struct with this    /// field for the duration of the returned reference.    #[expect(clippy::mut_from_ref)]    pub unsafe fn assert_mut(&self) -> &mut T {        // SAFETY: The caller has exclusive access to the `ListArc`, so they also have exclusive        // access to this field.        unsafe { &mut *self.value.get() }    }} /// Defines getters for a [`ListArcField`].#[macro_export]#[doc(hidden)]macro_rules! define_list_arc_field_getter {    ($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident }     $($rest:tt)*    ) => {        $pub fn $name<'a>(self: &'a $crate::list::ListArc<Self $(, $id)?>) -> &'a $typ {            let field = &(&**self).$field;            // SAFETY: We have a shared reference to the `ListArc`.            unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_ref(field) }        }         $crate::list::define_list_arc_field_getter!($($rest)*);    };     ($pub:vis fn $name:ident(&mut self $(<$id:tt>)?) -> &mut $typ:ty { $field:ident }     $($rest:tt)*    ) => {        $pub fn $name<'a>(self: &'a mut $crate::list::ListArc<Self $(, $id)?>) -> &'a mut $typ {            let field = &(&**self).$field;            // SAFETY: We have a mutable reference to the `ListArc`.            unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_mut(field) }        }         $crate::list::define_list_arc_field_getter!($($rest)*);    };     () => {};}pub use define_list_arc_field_getter;