basin2_lib/ilib/
atomic.rs1use std::fmt::{Debug, self};
2use std::sync::atomic::{ AtomicPtr, Ordering };
3use std::ptr::null_mut;
4
5pub struct Atomic<T: Send + Sync + Clone + Copy + 'static> {
8 item: AtomicPtr<T>,
9}
10
11impl<T: Send + Sync + Clone + Copy + 'static> Default for Atomic<T> {
12 fn default() -> Atomic<T> {
13 Atomic::new()
14 }
15}
16
17impl<T: Debug + Send + Sync + Clone + Copy + 'static> Debug for Atomic<T> {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 self.get().fmt(f)
20 }
21}
22
23impl<T: Send + Sync + Clone + Copy + 'static> Clone for Atomic<T> {
24 fn clone(&self) -> Self {
25 let ptr = self.item.load(Ordering::Relaxed);
26 let ptr = if ptr == null_mut::<T>() {
27 ptr
28 } else {
29 Box::into_raw(Box::new(self.get())) as *mut T
30 };
31 Atomic {
32 item: AtomicPtr::new(ptr),
33 }
34 }
35}
36
37impl<T: PartialEq + Send + Sync + Clone + Copy + 'static> PartialEq for Atomic<T> {
38 fn eq(&self, other: &Self) -> bool {
39 return self.get() == other.get();
40 }
41}
42
43impl<T: Send + Sync + Clone + Copy + 'static> Drop for Atomic<T> {
44 fn drop(&mut self) {
45 let ptr = self.item.load(Ordering::Relaxed);
46 if ptr != null_mut() {
47 drop(unsafe { Box::from_raw(ptr) });
48 }
49 }
50}
51
52impl<T: Send + Sync + Clone + Copy + 'static> From<T> for Atomic<T> {
53 fn from(item: T) -> Atomic<T> {
54 return Atomic {
55 item: AtomicPtr::new(Box::into_raw(Box::new(item)) as *mut T),
56 };
57 }
58}
59
60impl<T: Send + Sync + Clone + Copy + 'static> Atomic<T> {
61
62 pub fn new() -> Atomic<T> {
63 Atomic {
64 item: AtomicPtr::new(null_mut::<T>()),
65 }
66 }
67
68 pub fn set(&self, item: T) {
69 let boxed_item = Box::into_raw(Box::new(item)) as *mut T;
70 let old_item = self.item.swap(boxed_item, Ordering::Relaxed);
71 if old_item != null_mut() {
72 drop(unsafe { Box::from_raw(old_item) });
73 }
74 }
75
76 pub fn get(&self) -> T {
77 let ptr = self.item.load(Ordering::Relaxed);
78 if ptr == null_mut::<T>() {
79 panic!("attempt to get value of unset Atomic!");
80 }
81 return unsafe { *ptr };
82 }
83
84 pub fn is_set(&self) -> bool {
85 let ptr = self.item.load(Ordering::Relaxed);
86 ptr != null_mut::<T>()
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
95 struct TestStruct {
96 value: u32,
97 }
98
99 #[test]
100 fn test_ref_can_set() {
101 let setter = Atomic::<TestStruct>::new();
102 assert_eq!(setter.is_set(), false);
103 setter.set(TestStruct { value: 243523 });
104 assert_eq!(setter.is_set(), true);
105
106 assert_eq!(setter.get(), TestStruct { value: 243523 });
107 assert_eq!(setter.is_set(), true);
108 let gotten = setter.get();
109 drop(setter);
110 assert_eq!(gotten, TestStruct { value: 243523 });
111 }
112
113}