1use std::alloc;
2use std::cell::Cell;
3use std::cell::UnsafeCell;
4use std::fmt::Debug;
5use std::fmt::Formatter;
6use std::hash::Hash;
7use std::hash::Hasher;
8use std::marker::PhantomData;
9use std::ptr;
10use std::ptr::NonNull;
11
12pub(crate) struct Ptr<D: ?Sized> {
13 ptr: NonNull<StateCell<D>>,
14 phantom: PhantomData<StateCell<D>>,
15}
16
17#[derive(Copy, Clone, PartialEq, Eq, Hash)]
18pub struct State {
19 holder_cnt: isize,
22 viewer_cnt: isize,
25}
26
27impl<D: ?Sized> Ptr<D> {
28 pub(crate) fn new_holder(data: D) -> Self
29 where D: Sized {
30 Self::new(data, State::new_holder())
31 }
32
33 pub(crate) fn new_viewer(data: D) -> Self
34 where D: Sized {
35 Self::new(data, State::new_viewer())
36 }
37
38 pub(crate) fn new_owner(data: D) -> Self
39 where D: Sized {
40 Self::new(data, State::new_owner())
41 }
42
43 fn new(data: D, state: State) -> Self
44 where D: Sized {
45 let ptr = Box::leak(Box::new(StateCell::new(data, state)));
46 Ptr { ptr: NonNull::from_mut(ptr), phantom: PhantomData }
47 }
48
49 pub(crate) fn clone_to_holder(&self) -> Self {
50 self.cell().clone_to_holder();
51 Ptr { ptr: self.ptr, phantom: PhantomData }
52 }
53
54 pub(crate) fn clone_to_viewer(&self) -> Result<Self, State> {
55 self.cell().clone_to_viewer()?;
56 Ok(Ptr { ptr: self.ptr, phantom: PhantomData })
57 }
58
59 pub(crate) fn clone_to_owner(&self) -> Result<Self, State> {
60 self.cell().clone_to_owner()?;
61 Ok(Ptr { ptr: self.ptr, phantom: PhantomData })
62 }
63
64 pub(crate) fn drop_from_holder(&self) {
65 self.cell().drop_from_holder();
66 self.check_dealloc();
67 }
68
69 pub(crate) fn drop_from_viewer(&self) {
70 self.cell().drop_from_viewer();
71 self.check_dealloc();
72 }
73
74 pub(crate) fn drop_from_owner(&self) {
75 self.cell().drop_from_owner();
76 self.check_dealloc();
77 }
78
79 fn check_dealloc(&self) {
80 if self.cell().should_dealloc() {
81 let layout = alloc::Layout::for_value(self.cell());
82 unsafe {
87 alloc::dealloc(self.ptr.as_ptr().cast(), layout);
88 }
89 }
90 }
91
92 pub(crate) fn cell(&self) -> &StateCell<D> {
93 unsafe { self.ptr.as_ref() }
95 }
96}
97
98impl<D: ?Sized> Debug for Ptr<D> {
99 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
100 self.ptr.fmt(f)
101 }
102}
103
104impl<D: ?Sized> PartialEq for Ptr<D> {
105 fn eq(&self, other: &Self) -> bool {
106 ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr())
107 }
108}
109
110impl<D: ?Sized> Eq for Ptr<D> {}
111
112impl<D: ?Sized> Hash for Ptr<D> {
113 fn hash<H: Hasher>(&self, state: &mut H) {
114 self.ptr.hash(state);
115 }
116}
117
118pub(crate) struct StateCell<D: ?Sized> {
119 state: Cell<State>,
120 data: UnsafeCell<D>,
121}
122
123impl<D: ?Sized> StateCell<D> {
124 fn new(data: D, state: State) -> Self
125 where D: Sized {
126 StateCell { state: Cell::new(state), data: UnsafeCell::new(data) }
127 }
128
129 pub(crate) fn state(&self) -> State {
130 self.state.get()
131 }
132
133 fn clone_to_holder(&self) {
134 self.state.set(self.state.get().clone_to_holder());
135 }
136
137 fn clone_to_viewer(&self) -> Result<(), State> {
138 self.state.set(self.state.get().clone_to_viewer()?);
139 Ok(())
140 }
141
142 fn clone_to_owner(&self) -> Result<(), State> {
143 self.state.set(self.state.get().clone_to_owner()?);
144 Ok(())
145 }
146
147 fn drop_from_holder(&self) {
148 self.state.set(self.state.get().drop_from_holder());
149 self.check_drop_data();
150 }
151
152 fn drop_from_viewer(&self) {
153 self.state.set(self.state.get().drop_from_viewer());
154 self.check_drop_data();
155 }
156
157 fn drop_from_owner(&self) {
158 self.state.set(self.state.get().drop_from_owner());
159 self.check_drop_data();
160 }
161
162 fn check_drop_data(&self) {
163 if self.state.get().should_drop() {
164 unsafe { self.drop_data() }
166 }
167 }
168
169 pub(crate) unsafe fn move_data(&self) -> D
171 where D: Sized {
172 self.state.set(self.state.get().drop());
173 unsafe { ptr::read(self.data.get()) }
175 }
176
177 pub(crate) unsafe fn drop_data(&self) {
179 self.state.set(self.state.get().drop());
180 unsafe {
182 ptr::drop_in_place(self.data.get());
183 }
184 }
185
186 pub(crate) unsafe fn reinit_data(&self, d: D)
188 where D: Sized {
189 self.state.set(self.state.get().reinit());
190 unsafe {
192 ptr::write(self.data.get(), d);
193 }
194 }
195
196 fn should_dealloc(&self) -> bool {
197 self.state.get().should_dealloc()
198 }
199
200 pub(crate) unsafe fn deref<'a>(&self) -> &'a D {
202 unsafe { self.data.get().as_ref().unwrap() }
204 }
205
206 pub(crate) unsafe fn deref_mut<'a>(&self) -> &'a mut D {
208 unsafe { self.data.get().as_mut().unwrap() }
210 }
211
212 pub(crate) fn data_ptr(&self) -> *mut D {
213 self.data.get()
214 }
215}
216
217impl State {
218 pub fn is_dropped(&self) -> bool {
219 self.holder_cnt < 0
220 }
221
222 pub fn holder_count(&self) -> usize {
223 (self.holder_cnt & isize::MAX) as usize
224 }
225
226 pub fn viewer_count(&self) -> usize {
227 (self.viewer_cnt & isize::MAX) as usize
228 }
229
230 pub fn is_owned(&self) -> bool {
231 self.viewer_cnt < 0
232 }
233
234 fn new_holder() -> Self {
235 Self { holder_cnt: 1, viewer_cnt: 0 }
236 }
237
238 fn new_viewer() -> Self {
239 Self { holder_cnt: 0, viewer_cnt: 1 }
240 }
241
242 fn new_owner() -> Self {
243 Self { holder_cnt: 0, viewer_cnt: isize::MIN }
244 }
245
246 fn clone_to_holder(mut self) -> Self {
247 self.holder_cnt += 1;
248 self
249 }
250
251 fn clone_to_viewer(mut self) -> Result<Self, Self> {
252 if self.is_dropped() || self.is_owned() {
253 Err(self)
254 } else {
255 self.viewer_cnt += 1;
256 Ok(self)
257 }
258 }
259
260 fn clone_to_owner(mut self) -> Result<Self, Self> {
261 if self.is_dropped() || self.viewer_cnt != 0 {
262 Err(self)
263 } else {
264 self.viewer_cnt = isize::MIN;
265 Ok(self)
266 }
267 }
268
269 fn drop_from_holder(mut self) -> Self {
270 self.holder_cnt -= 1;
271 self
272 }
273
274 fn drop_from_viewer(mut self) -> Self {
275 self.viewer_cnt -= 1;
276 self
277 }
278
279 fn drop_from_owner(mut self) -> Self {
280 self.viewer_cnt = 0;
281 self
282 }
283
284 fn drop(mut self) -> Self {
285 self.holder_cnt |= isize::MIN;
286 self
287 }
288
289 fn reinit(mut self) -> Self {
290 self.holder_cnt &= isize::MAX;
291 self
292 }
293
294 fn should_drop(&self) -> bool {
296 self.holder_cnt == 0 && self.viewer_cnt == 0
297 }
298
299 fn should_dealloc(&self) -> bool {
300 self.holder_cnt == isize::MIN && self.viewer_cnt == 0
301 }
302}
303
304impl Debug for State {
305 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
306 f.debug_struct("State")
307 .field("dropped", &self.is_dropped())
308 .field("holder", &self.holder_count())
309 .field("viewer", &self.viewer_count())
310 .field("owned", &self.is_owned())
311 .finish()
312 }
313}