1 // SPDX-License-Identifier: GPL-2.0 2 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 pointers 8 //! has exclusive access to a field of the struct. 9 //! 10 //! [`ListArc`]: crate::list::ListArc 11 12 use core::cell::UnsafeCell; 13 14 /// A field owned by a specific [`ListArc`]. 15 /// 16 /// [`ListArc`]: crate::list::ListArc 17 pub 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. 22 unsafe 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. 24 unsafe impl<T: Send + Sync, const ID: u64> Sync for ListArcField<T, ID> {} 25 26 impl<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 /// # Safety 44 /// 45 /// The caller must have shared access to the `ListArc<ID>` containing the struct with this 46 /// 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 access 49 // 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 /// # Safety 56 /// 57 /// The caller must have mutable access to the `ListArc<ID>` containing the struct with this 58 /// 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 exclusive 62 // access to this field. 63 unsafe { &mut *self.value.get() } 64 } 65 } 66 67 /// Defines getters for a [`ListArcField`]. 68 #[macro_export] 69 macro_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 } 96 pub use define_list_arc_field_getter;
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.