1use std::sync::atomic::{AtomicPtr, Ordering};
2use std::sync::Arc;
3use std::ptr;
4
5pub struct AtomicArc<T> {
7 ptr: AtomicPtr<T>,
8}
9
10impl<T> AtomicArc<T> {
11 pub fn new(data: Option<T>) -> AtomicArc<T> {
13 let arc = data.map(|val| Arc::new(val));
14 AtomicArc::from_arc(arc)
15 }
16
17 pub fn from_arc(arc: Option<Arc<T>>) -> AtomicArc<T> {
19 let ptr = into_raw(arc) as *mut _;
20 let ptr = AtomicPtr::new(ptr);
21 AtomicArc {
22 ptr,
23 }
24 }
25
26 pub fn get_arc(&mut self) -> Option<Arc<T>> {
29 let ptr = *self.ptr.get_mut();
30 unsafe {
31 let arc = from_raw(ptr);
32 let ret = arc.clone();
33 let _ = into_raw(arc);
34 ret
35 }
36 }
37
38 pub fn get(&mut self) -> Option<&T> {
41 unsafe {
42 self.ptr.get_mut().as_ref()
43 }
44 }
45
46 pub fn into_arc(mut self) -> Option<Arc<T>> {
48 let ptr = *self.ptr.get_mut();
49 unsafe {
50 from_raw(ptr)
51 }
52 }
53
54 pub fn load(&self, order: Ordering) -> Option<Arc<T>> {
56 let ptr = self.ptr.load(order);
57 unsafe {
58 let arc = from_raw(ptr);
59 let ret = arc.clone();
60 let _ = into_raw(arc);
61 ret
62 }
63 }
64
65 pub fn store(&self, new: Option<Arc<T>>, order: Ordering) {
67 let _drop = self.swap(new, order);
68 }
69
70 pub fn swap(&self, new: Option<Arc<T>>, order: Ordering) -> Option<Arc<T>> {
73 let new_ptr = into_raw(new) as *mut _;
74 let old_ptr = self.ptr.swap(new_ptr, order);
75 unsafe {
76 from_raw(old_ptr)
77 }
78 }
79
80 pub fn compare_and_swap(
85 &self,
86 old: Option<Arc<T>>,
87 new: Option<Arc<T>>,
88 order: Ordering,
89 ) -> Option<Arc<T>> {
90 let old_ptr = into_raw(old) as *mut _;
91 let new_ptr = into_raw(new) as *mut _;
92 let prev_ptr = self.ptr.compare_and_swap(old_ptr, new_ptr, order);
93 if old_ptr == prev_ptr {
94 unsafe {
95 let _drop = from_raw(old_ptr);
96 from_raw(old_ptr)
97 }
98 } else {
99 unsafe {
100 from_raw(new_ptr)
101 }
102 }
103 }
104}
105
106fn into_raw<T>(a: Option<Arc<T>>) -> *const T {
107 a.map(|a| Arc::into_raw(a)).unwrap_or(ptr::null())
108}
109
110unsafe fn from_raw<T>(ptr: *const T) -> Option<Arc<T>> {
111 if ptr.is_null() {
112 None
113 } else {
114 Some(Arc::from_raw(ptr))
115 }
116}
117