1use core::ops::Deref;
2use core::ptr::NonNull;
3
4pub struct Strong<T: RefCnt + ?Sized>(NonNull<T>);
9
10impl<T: RefCnt + ?Sized> Strong<T> {
11 pub unsafe fn new(v: *const T) -> Self {
14 unsafe { (*v).increase_ref() };
15
16 Self(unsafe { NonNull::new_unchecked(v.cast_mut()) })
17 }
18
19 pub fn as_ptr(this: &Self) -> NonNull<T> {
20 this.0
21 }
22}
23
24impl<T: RefCnt + ?Sized> Drop for Strong<T> {
25 fn drop(&mut self) {
26 let v = self.0.as_ptr();
27 let r = unsafe { (*v).decrease_ref() };
28
29 if r == 1 {
30 unsafe { core::ptr::drop_in_place(v) };
31 }
32 }
33}
34
35impl<T: RefCnt + ?Sized> Deref for Strong<T> {
36 type Target = T;
37
38 fn deref(&self) -> &Self::Target {
39 unsafe { self.0.as_ref() }
40 }
41}
42
43impl<T: RefCnt + ?Sized> Clone for Strong<T> {
44 fn clone(&self) -> Self {
45 let v = self.0.as_ptr();
46
47 unsafe { (*v).increase_ref() };
48
49 Self(unsafe { NonNull::new_unchecked(v) })
50 }
51}
52
53unsafe impl<T: RefCnt + Send + ?Sized> Send for Strong<T> {}
54unsafe impl<T: RefCnt + Sync + ?Sized> Sync for Strong<T> {}
55
56pub unsafe trait RefCnt {
62 fn increase_ref(&self);
67
68 fn decrease_ref(&self) -> usize;
71}