// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. /*! Task-local garbage-collected boxes The `Gc` type provides shared ownership of an immutable value. Destruction is not deterministic, and will occur some time between every `Gc` handle being gone and the end of the task. The garbage collector is task-local so `Gc` is not sendable. */ #![experimental] #![allow(experimental)] use clone::Clone; use cmp::{Ord, PartialOrd, Ordering, Eq, PartialEq}; use default::Default; use fmt; use hash; use kinds::marker; use option::Option; use ops::Deref; use raw; /// Immutable garbage-collected pointer type #[lang="gc"] #[experimental = "Gc is currently based on reference-counting and will not collect cycles until \ task annihilation. For now, cycles need to be broken manually by using `Rc` \ with a non-owning `Weak` pointer. A tracing garbage collector is planned."] pub struct Gc { _ptr: *mut T, marker: marker::NoSend, } #[unstable] impl Clone for Gc { /// Clone the pointer only #[inline] fn clone(&self) -> Gc { *self } } /// An value that represents the task-local managed heap. /// /// Use this like `let foo = box(GC) Bar::new(...);` #[lang="managed_heap"] #[cfg(not(test))] pub static GC: () = (); impl PartialEq for Gc { #[inline] fn eq(&self, other: &Gc) -> bool { *(*self) == *(*other) } #[inline] fn ne(&self, other: &Gc) -> bool { *(*self) != *(*other) } } impl PartialOrd for Gc { #[inline] fn partial_cmp(&self, other: &Gc) -> Option { (**self).partial_cmp(&**other) } #[inline] fn lt(&self, other: &Gc) -> bool { *(*self) < *(*other) } #[inline] fn le(&self, other: &Gc) -> bool { *(*self) <= *(*other) } #[inline] fn ge(&self, other: &Gc) -> bool { *(*self) >= *(*other) } #[inline] fn gt(&self, other: &Gc) -> bool { *(*self) > *(*other) } } impl Ord for Gc { #[inline] fn cmp(&self, other: &Gc) -> Ordering { (**self).cmp(&**other) } } impl Eq for Gc {} impl Deref for Gc { fn deref<'a>(&'a self) -> &'a T { &**self } } impl Default for Gc { fn default() -> Gc { box(GC) Default::default() } } impl raw::Repr<*const raw::Box> for Gc {} impl + 'static> hash::Hash for Gc { fn hash(&self, s: &mut S) { (**self).hash(s) } } impl fmt::Show for Gc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) } } #[cfg(test)] mod tests { use prelude::*; use super::*; use cell::RefCell; #[test] fn test_managed_clone() { let a = box(GC) 5i; let b: Gc = a.clone(); assert!(a == b); } #[test] fn test_clone() { let x = Gc::new(RefCell::new(5)); let y = x.clone(); *x.borrow().borrow_mut() = 20; assert_eq!(*y.borrow().borrow(), 20); } #[test] fn test_simple() { let x = Gc::new(5); assert_eq!(*x.borrow(), 5); } #[test] fn test_simple_clone() { let x = Gc::new(5); let y = x.clone(); assert_eq!(*x.borrow(), 5); assert_eq!(*y.borrow(), 5); } #[test] fn test_ptr_eq() { let x = Gc::new(5); let y = x.clone(); let z = Gc::new(7); assert!(x.ptr_eq(&x)); assert!(x.ptr_eq(&y)); assert!(!x.ptr_eq(&z)); } #[test] fn test_destructor() { let x = Gc::new(box 5); assert_eq!(**x.borrow(), 5); } }