Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/list/arc_field.rs
29266 views
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
#[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]
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
98