xref: /linux/rust/kernel/list/arc_field.rs (revision 570172569238c66a482ec3eb5d766cc9cf255f69)
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`.
new(value: T) -> Self28     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`.
get_mut(&mut self) -> &mut T37     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.
assert_ref(&self) -> &T47     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)]
assert_mut(&self) -> &mut T60     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;
97