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