Created
November 6, 2016 02:11
-
-
Save Centril/43cd141d5b990de1319f1767ca0d3aeb to your computer and use it in GitHub Desktop.
OptArcMutex, mem::replace_with, mem_modify
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
// 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() {} |
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::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()); | |
} |
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::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