rt_own/
ptr.rs

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    // the sign bit indicates whether data has been dropped (negative)
20    // other bits indicates holder cnt
21    holder_cnt: isize,
22    // the sign bit indicates whether data has been owned (negative)
23    // other bits indicates viewer cnt
24    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            // SAFETY:
83            // state promises that we can and should dealloc
84            // we are the last Ptr accessible to the ptr of PtrCell, and we are dropped
85            // we carefully don't make any ref to PtrCell when calling dealloc
86            unsafe {
87                alloc::dealloc(self.ptr.as_ptr().cast(), layout);
88            }
89        }
90    }
91
92    pub(crate) fn cell(&self) -> &StateCell<D> {
93        // SAFETY: when self is alive, ptr is always valid, and we never call ptr.as_mut()
94        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            // SAFETY: state promises that we can and should drop
165            unsafe { self.drop_data() }
166        }
167    }
168
169    // SAFETY: call only once and there is no ref
170    pub(crate) unsafe fn move_data(&self) -> D
171    where D: Sized {
172        self.state.set(self.state.get().drop());
173        // SAFETY: call only once and there is no ref
174        unsafe { ptr::read(self.data.get()) }
175    }
176
177    // SAFETY: call only once and there is no ref
178    pub(crate) unsafe fn drop_data(&self) {
179        self.state.set(self.state.get().drop());
180        // SAFETY: call only once and there is no ref
181        unsafe {
182            ptr::drop_in_place(self.data.get());
183        }
184    }
185
186    // SAFETY: data is dropped
187    pub(crate) unsafe fn reinit_data(&self, d: D)
188    where D: Sized {
189        self.state.set(self.state.get().reinit());
190        // SAFETY: data is dropped
191        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    // SAFETY: make sure data not dropped and there is no mut ref
201    pub(crate) unsafe fn deref<'a>(&self) -> &'a D {
202        // SAFETY: make sure data not dropped and there is no mut ref
203        unsafe { self.data.get().as_ref().unwrap() }
204    }
205
206    // SAFETY: make sure data not dropped and there is no ref
207    pub(crate) unsafe fn deref_mut<'a>(&self) -> &'a mut D {
208        // SAFETY: make sure data not dropped and there is no ref
209        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    // if already dropped, return false
295    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}