cursed/
sync.rs

1use core::ffi::c_void;
2use alloc::sync::Arc;
3
4use crate::nullable::{null, Nullable};
5
6#[derive(Debug)]
7#[repr(transparent)]
8pub struct ArcPtr<T: ?Sized>(*const T);
9
10impl<T> ArcPtr<T> {
11    pub fn new(item: T) -> ArcPtr<T> {
12        ArcPtr::from(Arc::new(item))
13    }
14}
15
16impl<T: ?Sized> ArcPtr<T> {
17    #[doc(hidden)]
18    pub(crate) fn as_ptr(&self) -> *const T {
19        self.0
20    }
21
22    pub fn is_null(&self) -> bool {
23        self.0.is_null()
24    }
25
26    pub fn as_ref(&self) -> Option<&T> {
27        if self.is_null() {
28            None
29        } else {
30            Some(unsafe { &*self.0 })
31        }
32    }
33
34    pub fn into_arc(self) -> Arc<T> {
35        unsafe { Arc::from_raw(self.0 as *mut T) }
36    }
37}
38
39impl<T: ?Sized> core::ops::Deref for ArcPtr<T> {
40    type Target = T;
41
42    fn deref(&self) -> &Self::Target {
43        unsafe { &*self.0 }
44    }
45}
46
47impl<T: ?Sized> Clone for ArcPtr<T> {
48    fn clone(&self) -> ArcPtr<T> {
49        let arc = unsafe { Arc::from_raw(self.0) };
50        let arc1 = Arc::clone(&arc);
51        core::mem::forget(arc);
52        ArcPtr(Arc::into_raw(arc1))
53    }
54}
55
56impl<T: ?Sized> Drop for ArcPtr<T> {
57    fn drop(&mut self) {
58        unsafe { Arc::from_raw(self.0 as *mut c_void) };
59    }
60}
61
62impl<T: ?Sized> From<Arc<T>> for ArcPtr<T> {
63    fn from(arc: Arc<T>) -> ArcPtr<T> {
64        ArcPtr(Arc::into_raw(arc))
65    }
66}
67
68pub fn nullable_arc<T>(thing: T) -> Nullable<ArcPtr<T>> {
69    Nullable::from(ArcPtr::new(thing))
70}
71
72#[no_mangle]
73pub extern "C" fn arc_clone(arc: ArcPtr<c_void>) -> Nullable<ArcPtr<c_void>> {
74    match arc.is_null() {
75        true => null(),
76        false => Nullable::from(arc.clone()),
77    }
78}
79
80#[no_mangle]
81pub extern "C" fn arc_drop(arc: ArcPtr<c_void>) -> bool {
82    match arc.is_null() {
83        true => false,
84        false => {
85            arc.into_arc();
86            true
87        }
88    }
89}