1use std::sync::{atomic::{AtomicPtr, Ordering}, Arc, RwLock};
2
3#[derive(Debug)]
4struct Holder<T>{
5 ptr: AtomicPtr<T>,
6}
7#[derive(Debug)]
8pub struct AtomicSwap<T> {
9 holder: Arc<Holder<T>>,
10}
11
12impl<T> Clone for AtomicSwap<T> {
13 fn clone(&self) -> Self {
14 Self { holder: self.holder.clone() }
15 }
16}
17
18impl<T> AtomicSwap<T> {
19 pub fn from_value(v: T) -> Self{
20 let ptr = Arc::into_raw(Arc::new(v)) as * mut _;
21 AtomicSwap { holder: Arc::new(Holder{ptr: AtomicPtr::new(ptr)})}
22 }
23
24 pub fn load(&self) -> Arc<T> {
25 let ptr = self.holder.as_ref().ptr.load(Ordering::Acquire);
26 let v = unsafe {Arc::from_raw(ptr)};
27 let v2 = v.clone();
28 assert_eq!(ptr, Arc::into_raw(v) as * mut _);
29 v2
30 }
31
32 pub fn swap(&self, v: T) -> Arc<T> {
33 let new_ptr = Arc::into_raw(Arc::new(v)) as * mut _;
34 let ptr = self.holder.as_ref().ptr.swap(new_ptr, Ordering::AcqRel);
35 let v = unsafe {Arc::from_raw(ptr)};
36 v
37 }
38}
39
40impl<T> Drop for Holder<T> {
41 fn drop(&mut self) {
42 let _arc = unsafe {Arc::from_raw(self.ptr.load(Ordering::Acquire))};
43 }
44}
45#[derive(Debug)]
46pub struct V{
47 pub v: u32
48}
49impl Drop for V{
50 fn drop(&mut self) {
51 println!("drop V: {:?}", self);
52 }
53}
54#[inline(never)]
55pub fn load_test2(v: &Arc<RwLock<V>>) -> u32{
56 v.read().unwrap().v
57}
58
59#[cfg(test)]
60mod test {
61 use std::time::Duration;
62
63 use super::*;
64 #[test]
65 fn multiple_threads(){
66 let v = AtomicSwap::from_value(V{v: 3});
67 let v2 = v.clone();
68 let t1 = std::thread::spawn(move || {
69 println!("t1: {:?}", v2.load());
70 std::thread::sleep(Duration::from_millis(100));
71 println!("t1: {:?}", v2.load());
72 });
73 std::thread::sleep(Duration::from_millis(50));
74 v.swap(V{v: 10});
75 t1.join().unwrap();
76 }
77}