Skip to content

Instantly share code, notes, and snippets.

@jhecking
Last active March 9, 2017 03:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhecking/996f6c3d6edc7da2b18ab044a4a1f687 to your computer and use it in GitHub Desktop.
Save jhecking/996f6c3d6edc7da2b18ab044a4a1f687 to your computer and use it in GitHub Desktop.
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);
}
}
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