1use std::{
2 alloc::{
3 Layout,
4 dealloc,
5 },
6 ptr::NonNull,
7 sync::atomic::Ordering,
8};
9
10use crate::{
11 ops::place::{
12 BorrowPlace,
13 CreateHandle,
14 DerefPlace,
15 PlaceHandle,
16 PlaceProxy,
17 ProjectPlace,
18 ReadPlace,
19 borrowck::{
20 AccessKind,
21 Instant,
22 Lifetime,
23 Timing,
24 UntilDrop,
25 },
26 },
27 place::Subplace,
28 sync::arc::ArcHead,
29};
30
31pub struct ArcRef<T: ?Sized> {
35 pub(super) head: NonNull<ArcHead>,
36 pub(super) layout: Layout,
37 pub(super) data: NonNull<T>,
38}
39
40impl<T: ?Sized> Drop for ArcRef<T> {
41 fn drop(&mut self) {
42 let strong = unsafe { &(*self.head.as_ptr()).strong };
43 let old = strong.fetch_sub(1, Ordering::Relaxed);
44 if old == 1 {
45 let layout = self.layout;
46 let ptr: *mut u8 = self.head.as_ptr().cast();
47 unsafe { dealloc(ptr, layout) };
48 }
49 }
50}
51
52impl<T: ?Sized> PlaceProxy for ArcRef<T> {
53 type Target = T;
54}
55
56unsafe impl<T: ?Sized> CreateHandle<Instant> for ArcRef<T> {
57 type Handle = ArcRefHandle<T>;
58
59 const ACCESS: AccessKind = AccessKind::Shared;
60
61 unsafe fn handle_from_raw(this: *const Self) -> Self::Handle {
62 let head = unsafe { (*this).head };
63 let layout = unsafe { (*this).layout };
64 let data = unsafe { (*this).data };
65 ArcRefHandle { head, layout, data }
66 }
67}
68
69pub struct ArcRefHandle<T: ?Sized> {
70 pub(super) head: NonNull<ArcHead>,
71 pub(super) layout: Layout,
72 pub(super) data: NonNull<T>,
73}
74
75impl<T: ?Sized> PlaceHandle for ArcRefHandle<T> {
76 type Target = T;
77}
78
79unsafe impl<T> ReadPlace for ArcRefHandle<T> {
80 const ACCESS: AccessKind = AccessKind::Shared;
81 const SAFE: bool = true;
82
83 unsafe fn read_place(self) -> Self::Target {
84 unsafe { self.data.read() }
85 }
86}
87
88unsafe impl<S: Subplace> ProjectPlace<S> for ArcRefHandle<S::Source> {
89 type Projected = ArcRefHandle<S::Target>;
90
91 unsafe fn project_place(self, subplace: S) -> Self::Projected {
92 let Self { head, layout, data } = self;
93 ArcRefHandle {
94 head,
95 layout,
96 data: unsafe { data.project_place(subplace) },
97 }
98 }
99}
100
101unsafe impl<T: ?Sized> BorrowPlace<ArcRef<T>> for ArcRefHandle<T> {
102 const ACCESS: AccessKind = AccessKind::Shared;
103 type Timing = Instant;
104 const SAFE: bool = true;
105
106 unsafe fn borrow(self) -> ArcRef<T> {
107 let ArcRefHandle { head, layout, data } = self;
108 unsafe {
109 let strong = &(*head.as_ptr()).strong;
110 let old = strong.fetch_add(1, Ordering::Relaxed);
111 {
match (&old, &0) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_ne!(old, 0);
112 }
113 ArcRef { head, layout, data }
114 }
115}
116
117unsafe impl<T: ?Sized> BorrowPlace<*const T> for ArcRefHandle<T> {
118 const ACCESS: AccessKind = AccessKind::Shared;
119 type Timing = Instant;
120 const SAFE: bool = true;
121
122 unsafe fn borrow(self) -> *const T {
123 self.data.as_ptr()
124 }
125}
126
127unsafe impl<T: ?Sized> BorrowPlace<NonNull<T>> for ArcRefHandle<T> {
128 const ACCESS: AccessKind = AccessKind::Shared;
129 type Timing = Instant;
130 const SAFE: bool = true;
131
132 unsafe fn borrow(self) -> NonNull<T> {
133 self.data
134 }
135}
136
137unsafe impl<'a, T: ?Sized> BorrowPlace<&'a T> for ArcRefHandle<T> {
138 const ACCESS: AccessKind = AccessKind::Shared;
139 type Timing = Lifetime<'a>;
140 const SAFE: bool = true;
141
142 unsafe fn borrow(self) -> &'a T {
143 unsafe { self.data.as_ref() }
144 }
145}
146
147unsafe impl<T, ProxyTiming> DerefPlace<ProxyTiming, UntilDrop>
148 for ArcRefHandle<T>
149where
150 T: ?Sized + CreateHandle<ProxyTiming>,
151 ProxyTiming: Timing,
152{
153 const POINTEE_ACCESS: AccessKind = T::ACCESS;
154 const POINTER_ACCESS: AccessKind = AccessKind::Shared;
155 const SAFE: bool = true;
156
157 unsafe fn deref_place(
158 self,
159 ) -> <Self::Target as CreateHandle<ProxyTiming>>::Handle {
160 let ptr = self.data.as_ptr();
161 unsafe { T::handle_from_raw(ptr) }
162 }
163}