97 lines · rust
1// SPDX-License-Identifier: GPL-2.02 3// Copyright (C) 2024 Google LLC.4 5//! A field that is exclusively owned by a [`ListArc`].6//!7//! This can be used to have reference counted struct where one of the reference counted pointers8//! has exclusive access to a field of the struct.9//!10//! [`ListArc`]: crate::list::ListArc11 12use core::cell::UnsafeCell;13 14/// A field owned by a specific [`ListArc`].15///16/// [`ListArc`]: crate::list::ListArc17pub struct ListArcField<T, const ID: u64 = 0> {18 value: UnsafeCell<T>,19}20 21// SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.22unsafe impl<T: Send + Sync, const ID: u64> Send for ListArcField<T, ID> {}23// SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.24unsafe impl<T: Send + Sync, const ID: u64> Sync for ListArcField<T, ID> {}25 26impl<T, const ID: u64> ListArcField<T, ID> {27 /// Creates a new `ListArcField`.28 pub fn new(value: T) -> Self {29 Self {30 value: UnsafeCell::new(value),31 }32 }33 34 /// Access the value when we have exclusive access to the `ListArcField`.35 ///36 /// This allows access to the field using an `UniqueArc` instead of a `ListArc`.37 pub fn get_mut(&mut self) -> &mut T {38 self.value.get_mut()39 }40 41 /// Unsafely assert that you have shared access to the `ListArc` for this field.42 ///43 /// # Safety44 ///45 /// The caller must have shared access to the `ListArc<ID>` containing the struct with this46 /// field for the duration of the returned reference.47 pub unsafe fn assert_ref(&self) -> &T {48 // SAFETY: The caller has shared access to the `ListArc`, so they also have shared access49 // to this field.50 unsafe { &*self.value.get() }51 }52 53 /// Unsafely assert that you have mutable access to the `ListArc` for this field.54 ///55 /// # Safety56 ///57 /// The caller must have mutable access to the `ListArc<ID>` containing the struct with this58 /// field for the duration of the returned reference.59 #[allow(clippy::mut_from_ref)]60 pub unsafe fn assert_mut(&self) -> &mut T {61 // SAFETY: The caller has exclusive access to the `ListArc`, so they also have exclusive62 // access to this field.63 unsafe { &mut *self.value.get() }64 }65}66 67/// Defines getters for a [`ListArcField`].68#[macro_export]69macro_rules! define_list_arc_field_getter {70 ($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident }71 $($rest:tt)*72 ) => {73 $pub fn $name<'a>(self: &'a $crate::list::ListArc<Self $(, $id)?>) -> &'a $typ {74 let field = &(&**self).$field;75 // SAFETY: We have a shared reference to the `ListArc`.76 unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_ref(field) }77 }78 79 $crate::list::define_list_arc_field_getter!($($rest)*);80 };81 82 ($pub:vis fn $name:ident(&mut self $(<$id:tt>)?) -> &mut $typ:ty { $field:ident }83 $($rest:tt)*84 ) => {85 $pub fn $name<'a>(self: &'a mut $crate::list::ListArc<Self $(, $id)?>) -> &'a mut $typ {86 let field = &(&**self).$field;87 // SAFETY: We have a mutable reference to the `ListArc`.88 unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_mut(field) }89 }90 91 $crate::list::define_list_arc_field_getter!($($rest)*);92 };93 94 () => {};95}96pub use define_list_arc_field_getter;97