Skip to content

Instantly share code, notes, and snippets.

@rlepidi
Created March 5, 2014 15:28
Show Gist options
  • Save rlepidi/9369457 to your computer and use it in GitHub Desktop.
Save rlepidi/9369457 to your computer and use it in GitHub Desktop.
use std::sync::arc::UnsafeArc;
use std::cast;
use std::comm::Chan;
pub struct ArcRefCell<T> {
priv inner: UnsafeArc<T>
}
impl<T: Send> ArcRefCell<T> {
pub fn new(value: T) -> ArcRefCell<T> {
ArcRefCell { inner: UnsafeArc::new(value) }
}
pub fn borrow(&self) -> ArcRef<T> {
ArcRef::new(self.inner.clone())
}
pub fn borrow_mut(&self) -> ArcRefMut<T> {
assert!(self.can_borrow_mut());
ArcRefMut::new(self.inner.clone())
}
pub fn can_borrow_mut(&self) -> bool {
self.inner.is_owned()
}
}
pub struct ArcRef<T> {
priv inner: UnsafeArc<T>
}
impl<T: Send> ArcRef<T> {
fn new(inner: UnsafeArc<T>) -> ArcRef<T> {
ArcRef { inner: inner }
}
pub fn get<'a>(&'a self) -> &'a T {
unsafe { cast::transmute(self.inner.get_immut()) }
}
}
pub struct ArcRefMut<T> {
priv inner: UnsafeArc<T>
}
impl<T: Send> ArcRefMut<T> {
fn new(inner: UnsafeArc<T>) -> ArcRefMut<T> {
ArcRefMut { inner: inner }
}
pub fn get<'a>(&'a self) -> &'a mut T {
unsafe { cast::transmute(self.inner.get()) }
}
}
#[test]
#[allow(unused_variable)]
fn test_borrow_mut() {
let ref_cell = ArcRefCell::new(3);
assert!(ref_cell.can_borrow_mut());
{
let borrow = ref_cell.borrow();
assert!(!ref_cell.can_borrow_mut());
let borrow2 = ref_cell.borrow();
assert!(!ref_cell.can_borrow_mut());
}
assert!(ref_cell.can_borrow_mut());
}
#[test]
#[should_fail]
#[allow(unused_variable)]
fn test_borrow_mut_failure() {
let ref_cell = ArcRefCell::new(3);
let borrow = ref_cell.borrow();
ref_cell.borrow_mut();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment