obkrnl/context/arc.rs
1use alloc::sync::Arc;
2use core::ops::Deref;
3
4/// Provides an access to the value of [Arc](alloc::sync::Arc) on [Context](super::Context) without
5/// cloning a reference.
6///
7/// We need this type because return a reference from [Context](super::Context) require static
8/// lifetime, which allow the caller to store it at a global level. Once the value is destroyed that
9/// reference will be invalid. We can solve this by return a cloned [Arc](alloc::sync::Arc) but most
10/// of the time the caller just want a temporary access to the value, which mean the increment and
11/// decrement of a reference is not needed so we invent this type to solve this problem.
12///
13/// This type work by making itself not [Send] and [Sync], which prevent the caller from storing it
14/// at a global level.
15#[repr(transparent)]
16pub struct BorrowedArc<T>(*const T); // A pointer make this type automatically !Send and !Sync.
17
18impl<T> BorrowedArc<T> {
19 /// # Safety
20 /// `v` must be owned by [Arc](alloc::sync::Arc) if not null.
21 pub(super) const unsafe fn new(v: *const T) -> Option<Self> {
22 if v.is_null() { None } else { Some(Self(v)) }
23 }
24
25 /// # Safety
26 /// `v` must be owned by [Arc](alloc::sync::Arc).
27 pub(super) const unsafe fn from_non_null(v: *const T) -> Self {
28 Self(v)
29 }
30
31 /// Note that this is an associated function, which means that you have to call it as
32 /// `BorrowedArc::as_ptr(v)` instead of `v.as_ptr()`. This is so that there is no conflict with
33 /// a method on the inner type.
34 pub fn as_ptr(this: &Self) -> *const T {
35 this.0
36 }
37
38 pub fn into_owned(self) -> Arc<T> {
39 // SAFETY: This is safe because the requirement of new() and from_non_null().
40 unsafe { Arc::increment_strong_count(self.0) };
41 unsafe { Arc::from_raw(self.0) }
42 }
43}
44
45impl<T> Clone for BorrowedArc<T> {
46 fn clone(&self) -> Self {
47 *self
48 }
49}
50
51impl<T> Copy for BorrowedArc<T> {}
52
53impl<T> Deref for BorrowedArc<T> {
54 type Target = T;
55
56 fn deref(&self) -> &Self::Target {
57 unsafe { &*self.0 }
58 }
59}