-
-
Save jhecking/996f6c3d6edc7da2b18ab044a4a1f687 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fmt::Debug; | |
use std::mem; | |
use std::ops::Deref; | |
use std::sync::atomic::{AtomicPtr, Ordering}; | |
use std::sync::{Arc}; | |
pub struct AtomicValue<T: Clone + Debug> { | |
data: AtomicPtr<Arc<T>> | |
} | |
impl<T: Clone + Debug> Drop for AtomicValue<T> { | |
fn drop(&mut self) { | |
println!("dropping atomic value"); | |
let ptr: *mut Arc<T> = self.data.load(Ordering::SeqCst); | |
println!("ptr={:?}", ptr); | |
let arc: &Arc<T> = unsafe { &*ptr }; | |
println!("arc={:?}", arc); | |
drop(arc); | |
} | |
} | |
impl<T: Clone + Debug> AtomicValue<T> { | |
pub fn new(t: T) -> Self { | |
let mut arc = Arc::new(t); | |
let ptr: *mut Arc<T> = &mut arc; | |
mem::forget(arc); | |
println!("ptr={:?}", ptr); | |
AtomicValue { | |
data: AtomicPtr::new(ptr), | |
} | |
} | |
pub fn borrow(&self) -> Arc<T> { | |
println!("borrow called"); | |
let ptr: *mut Arc<T> = self.data.load(Ordering::SeqCst); | |
println!("ptr={:?}", ptr); | |
let arc: &Arc<T> = unsafe { &*ptr }; | |
println!("arc={:?}, strong refs={}", arc, Arc::strong_count(&arc)); | |
arc.clone() | |
} | |
pub fn copy(&self) -> T { | |
println!("copy called"); | |
let ptr: *mut Arc<T> = self.data.load(Ordering::SeqCst); | |
println!("ptr={:?}", ptr); | |
let arc: &Arc<T> = unsafe { &*ptr }; | |
println!("arc={:?}, strong refs={}", arc, Arc::strong_count(&arc)); | |
let value: &T = arc.deref(); | |
value.clone() | |
} | |
pub fn replace(&self, t: T) { | |
println!("replace called - {:?}", t); | |
let mut arc = Arc::new(t); | |
let ptr: *mut Arc<T> = &mut arc; | |
mem::forget(arc); | |
println!("ptr={:?}", ptr); | |
let old_ptr: *mut Arc<T> = self.data.swap(ptr, Ordering::SeqCst); | |
println!("old_ptr={:?}", old_ptr); | |
let old_arc: &Arc<T> = unsafe { &*old_ptr }; | |
println!("old_arc={:?}, strong refs={}", old_arc, Arc::strong_count(&old_arc)); | |
drop(old_arc); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate rand; | |
use std::sync::{Arc}; | |
use std::thread; | |
use std::thread::JoinHandle; | |
use std::time::Duration; | |
use std::collections::HashMap; | |
mod atomic_value; | |
use atomic_value::AtomicValue; | |
#[derive(Clone, Debug)] | |
struct Value { | |
inner: HashMap<String, u32>, | |
} | |
impl Value { | |
pub fn new() -> Self { | |
Value { | |
inner: HashMap::new(), | |
} | |
} | |
pub fn get(&self) -> u32 { | |
*self.inner.get("gen").unwrap_or(&0u32) | |
} | |
pub fn set(&mut self, i: u32) { | |
self.inner.insert("gen".into(), i); | |
} | |
} | |
impl Drop for Value { | |
fn drop(&mut self) { | |
println!("{:?} - dropping {:?}", thread::current().name(), self.inner); | |
} | |
} | |
fn main() { | |
let atomic = Arc::new(AtomicValue::new(Value::new())); | |
let mut guards = vec![]; | |
guards.push(reader(atomic.clone(), "reader1".to_string())); | |
guards.push(reader(atomic.clone(), "reader2".to_string())); | |
guards.push(writer(atomic.clone(), "writer".to_string())); | |
drop(atomic); | |
for guard in guards { | |
guard.join().unwrap(); | |
} | |
println!("bye bye!"); | |
} | |
fn reader(atomic: Arc<AtomicValue<Value>>, name: String) -> JoinHandle<()> { | |
println!("starting reader"); | |
let shared = atomic.clone(); | |
thread::Builder::new().name(name).spawn(move || { | |
loop { | |
let borrowed = shared.borrow(); | |
thread::sleep(Duration::from_millis(100u64 + rand::random::<u64>() % 900u64)); | |
println!("{:?} - read={:?}", thread::current().name(), borrowed.get()); | |
if borrowed.get() == 9 { | |
break | |
} | |
} | |
println!("{:?} finished!", thread::current().name()); | |
}).unwrap() | |
} | |
fn writer(atomic: Arc<AtomicValue<Value>>, name: String) -> JoinHandle<()> { | |
println!("starting writer"); | |
thread::Builder::new().name(name).spawn(move || { | |
for i in 0..10 { | |
let mut copy = atomic.copy(); | |
thread::sleep(Duration::from_millis(100u64 + rand::random::<u64>() % 900u64)); | |
copy.set(i); | |
println!("{:?} - write={:?}", thread::current().name(), copy.get()); | |
atomic.replace(copy); | |
} | |
println!("{:?} finished!", thread::current().name()); | |
}).unwrap() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment