xref: /linux/rust/kernel/list/arc_field.rs (revision 570172569238c66a482ec3eb5d766cc9cf255f69)
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