1use crate::lock_token::LockToken;
6use core::marker::PhantomData;
7
8#[repr(transparent)]
14pub struct KCell<T, Class> {
15 value: core::cell::UnsafeCell<T>,
16 _marker: PhantomData<Class>,
17}
18
19unsafe impl<T: Send, Class> Sync for KCell<T, Class> {}
20unsafe impl<T: Send, Class> Send for KCell<T, Class> {}
21
22impl<T, Class> KCell<T, Class> {
23 #[inline]
25 pub const fn new(value: T) -> Self {
26 Self { value: core::cell::UnsafeCell::new(value), _marker: PhantomData }
27 }
28
29 #[inline]
38 pub unsafe fn get<'b>(&self, _token: &'b LockToken<'_, Class>) -> &'b T {
39 unsafe { &*self.value.get() }
43 }
44
45 #[inline]
54 pub unsafe fn get_mut<'b>(&self, _token: &'b mut LockToken<'_, Class>) -> &'b mut T {
55 unsafe { &mut *self.value.get() }
61 }
62
63 #[inline]
70 pub unsafe fn as_mut_ptr(&self, _token: &mut LockToken<'_, Class>) -> *mut T {
71 self.value.get()
72 }
73
74 #[inline]
77 pub fn get_inner_mut(&mut self) -> &mut T {
78 self.value.get_mut()
79 }
80
81 #[inline]
83 pub fn into_inner(self) -> T {
84 self.value.into_inner()
85 }
86}
87
88impl<T: Default, Class> Default for KCell<T, Class> {
89 #[inline]
90 fn default() -> Self {
91 Self::new(T::default())
92 }
93}
94
95impl<T, Class> From<T> for KCell<T, Class> {
96 #[inline]
97 fn from(value: T) -> Self {
98 Self::new(value)
99 }
100}
101
102impl<T, Class> AsMut<T> for KCell<T, Class> {
103 #[inline]
104 fn as_mut(&mut self) -> &mut T {
105 self.get_inner_mut()
106 }
107}
108
109impl<T, Class> core::fmt::Debug for KCell<T, Class> {
110 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111 f.debug_struct("KCell")
112 .field("value", &"<locked>")
113 .field("class", &core::any::type_name::<Class>())
114 .finish()
115 }
116}
117
118#[inline]
120pub fn kcell_init<I, Class>(init: I) -> KCellInit<I, Class> {
121 KCellInit(init, PhantomData)
122}
123
124pub struct KCellInit<I, Class>(I, PhantomData<Class>);
126
127unsafe impl<T, Class, I, E> pin_init::PinInit<KCell<T, Class>, E> for KCellInit<I, Class>
130where
131 I: pin_init::PinInit<T, E>,
132{
133 unsafe fn __pinned_init(self, slot: *mut KCell<T, Class>) -> Result<(), E> {
134 unsafe { self.0.__pinned_init(slot as *mut T) }
137 }
138}
139
140#[cfg(not(feature = "kernel"))]
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use lockdep::LockClass;
145
146 struct MyClass;
147 impl LockClass for MyClass {
148 const ID: *mut core::ffi::c_void = core::ptr::null_mut();
149 }
150
151 #[test]
152 fn test_kcell_default() {
153 let cell: KCell<u32, MyClass> = KCell::default();
154 unsafe {
155 let token = LockToken::new();
156 assert_eq!(*cell.get(&token), 0);
157 }
158 }
159
160 #[test]
161 fn test_kcell_exclusive_access() {
162 let mut cell: KCell<u32, MyClass> = KCell::new(10);
163 *cell.get_inner_mut() = 20;
164 let reference: &mut u32 = cell.as_mut();
165 *reference = 30;
166 let value = cell.into_inner();
167 assert_eq!(value, 30);
168 }
169
170 #[test]
171 fn test_kcell_as_mut_ptr() {
172 let cell: KCell<u32, MyClass> = KCell::new(100u32);
173 unsafe {
174 let mut token = LockToken::new();
175 let ptr = cell.as_mut_ptr(&mut token);
176 assert_eq!(*ptr, 100);
177 }
178 }
179
180 #[test]
181 fn test_kcell_debug() {
182 extern crate std;
183 let cell: KCell<u32, MyClass> = KCell::new(5);
184 let debug_str = std::format!("{:?}", cell);
185 assert!(debug_str.contains("KCell"));
186 assert!(debug_str.contains("<locked>"));
187 assert!(debug_str.contains("MyClass"));
188 }
189
190 #[test]
191 fn test_kcell_init() {
192 let init = unsafe {
193 pin_init::pin_init_from_closure(|slot: *mut u32| {
194 slot.write(42);
195 Ok::<(), core::convert::Infallible>(())
196 })
197 };
198 let cell_init = kcell_init::<_, MyClass>(init);
199
200 pin_init::stack_pin_init!(let cell = cell_init);
201 let cell: core::pin::Pin<&mut KCell<u32, MyClass>> = cell;
202
203 unsafe {
204 let token = LockToken::<MyClass>::new();
205 let val = cell.as_ref().get_ref().get(&token);
206 assert_eq!(*val, 42);
207 }
208 }
209}