Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
 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
12use core::cell::UnsafeCell;
13
14/// A field owned by a specific [`ListArc`].
15///
16/// [`ListArc`]: crate::list::ListArc
17pub 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    /// # 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    #[expect(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]
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;