Skip to content

Instantly share code, notes, and snippets.

@Centril
Created November 6, 2016 02:11
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 Centril/43cd141d5b990de1319f1767ca0d3aeb to your computer and use it in GitHub Desktop.
Save Centril/43cd141d5b990de1319f1767ca0d3aeb to your computer and use it in GitHub Desktop.
OptArcMutex, mem::replace_with, mem_modify
// naive implementation, see:
// https://github.com/rust-lang/rfcs/pull/1736
pub fn mem_modify<T, U, F>(r: &mut T, fun: F) -> U
where F: FnOnce(T) -> (T, U) {
use std::{ptr, mem};
unsafe {
let mut tmp = mem::uninitialized();
ptr::copy_nonoverlapping(r, &mut tmp, 1);
let (replace, retr) = fun(tmp);
ptr::copy_nonoverlapping(&replace, r, 1);
retr
}
}
fn main() {}
use std::sync::{Arc, Mutex, MutexGuard, LockResult, PoisonError};
pub enum OptArcMutex<T> {
Arc(Arc<Mutex<T>>),
Imm(T)
}
pub enum MGuard<'a, T: 'a> {
Real(MutexGuard<'a, T>),
Fake(&'a mut T)
}
impl<T> OptArcMutex<T> {
pub fn ensure_arc(&mut self) -> Arc<Mutex<T>> {
unsafe {
use std::{ptr, mem};
let mut tmp = mem::uninitialized();
ptr::copy_nonoverlapping(self, &mut tmp, 1);
let arc = match tmp {
OptArcMutex::Arc(a) => a,
OptArcMutex::Imm(b) => Arc::new(Mutex::new(b))
};
let clone = arc.clone();
let replace = OptArcMutex::Arc(arc);
ptr::copy_nonoverlapping(&replace, self, 1);
clone
}
}
pub fn lock(&mut self) -> LockResult<MGuard<T>> {
use OptArcMutex::*;
use MGuard::*;
match self {
&mut Arc(ref mg) => match mg.lock() {
Ok(a) => Ok(Real(a)),
Err(e) => Err(PoisonError::new(Real(e.into_inner())))
},
&mut Imm(ref mut t) => Ok(Fake(t))
}
}
}
use std::ops::{Deref, DerefMut};
impl<'a, T: 'a> Deref for MGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
use MGuard::*;
match self {
&Real(ref mg) => mg.deref(),
&Fake(ref t) => t
}
}
}
impl <'a, T: 'a> DerefMut for MGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
use MGuard::*;
match self {
&mut Real(ref mut mg) => mg.deref_mut(),
&mut Fake(ref mut t) => t
}
}
}
fn main() {
use std::thread;
use std::sync::mpsc;
let mut oam = OptArcMutex::Imm(42);
println!("{}", *oam.lock().unwrap());
let clone = oam.ensure_arc();
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
loop {
let mut m = clone.lock().unwrap();
*m = 1;
tx.send(*m).unwrap();
}
});
println!("{}", rx.recv().unwrap());
println!("{}", *oam.lock().unwrap());
}
use std::sync::{Arc, Mutex, MutexGuard, LockResult, PoisonError};
pub enum OptArcMutex<T> {
Arc(Arc<Mutex<T>>),
Imm(Option<T>)
}
pub enum MGuard<'a, T: 'a> {
Real(MutexGuard<'a, T>),
Fake(&'a mut T)
}
impl<T> OptArcMutex<T> {
pub fn ensure_arc(&mut self) -> Arc<Mutex<T>> {
let t = match *self {
OptArcMutex::Arc(ref arc) => return arc.clone(),
OptArcMutex::Imm(ref mut opt) => opt.take().unwrap(),
};
let arc = Arc::new(Mutex::new(t));
*self = OptArcMutex::Arc(arc.clone());
arc
}
pub fn lock(&mut self) -> LockResult<MGuard<T>> {
use OptArcMutex::*;
use MGuard::*;
match self {
&mut Arc(ref mg) => match mg.lock() {
Ok(a) => Ok(Real(a)),
Err(e) => Err(PoisonError::new(Real(e.into_inner())))
},
&mut Imm(ref mut t) => Ok(Fake(t.as_mut().unwrap()))
}
}
}
use std::ops::{Deref, DerefMut};
impl<'a, T: 'a> Deref for MGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
use MGuard::*;
match self {
&Real(ref mg) => mg.deref(),
&Fake(ref t) => t
}
}
}
impl <'a, T: 'a> DerefMut for MGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
use MGuard::*;
match self {
&mut Real(ref mut mg) => mg.deref_mut(),
&mut Fake(ref mut t) => t
}
}
}
fn main() {
use std::thread;
use std::sync::mpsc;
let mut oam = OptArcMutex::Imm(Some(42));
println!("{}", *oam.lock().unwrap());
let clone = oam.ensure_arc();
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
loop {
let mut m = clone.lock().unwrap();
*m = 1;
tx.send(*m).unwrap();
}
});
println!("{}", rx.recv().unwrap());
println!("{}", *oam.lock().unwrap());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment