diff --git a/src/libstd/gc.rs b/src/libstd/gc.rs new file mode 100644 index 0000000000000..5e2ba808d3115 --- /dev/null +++ b/src/libstd/gc.rs @@ -0,0 +1,99 @@ +// 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. + +*/ + +use kinds::Send; +use clone::{Clone, DeepClone}; + +/// Immutable garbage-collected pointer type +#[no_send] +#[deriving(Clone)] +pub struct Gc { + priv ptr: @T +} + +impl Gc { + /// Construct a new garbage-collected box + #[inline] + pub fn new(value: T) -> Gc { + Gc { ptr: @value } + } +} + +impl Gc { + /// Borrow the value contained in the garbage-collected box + #[inline] + pub fn borrow<'r>(&'r self) -> &'r T { + &*self.ptr + } +} + +/// The `Send` bound restricts this to acyclic graphs where it is well-defined. +/// +/// A `Freeze` bound would also work, but `Send` *or* `Freeze` cannot be expressed. +impl DeepClone for Gc { + #[inline] + fn deep_clone(&self) -> Gc { + Gc::new(self.borrow().deep_clone()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use cell::Cell; + + #[test] + fn test_clone() { + let x = Gc::new(Cell::new(5)); + let y = x.clone(); + do x.borrow().with_mut_ref |inner| { + *inner = 20; + } + assert_eq!(y.borrow().take(), 20); + } + + #[test] + fn test_deep_clone() { + let x = Gc::new(Cell::new(5)); + let y = x.deep_clone(); + do x.borrow().with_mut_ref |inner| { + *inner = 20; + } + assert_eq!(y.borrow().take(), 5); + } + + #[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_destructor() { + let x = Gc::new(~5); + assert_eq!(**x.borrow(), 5); + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index e0908dcb290b2..ffa91df4e8a86 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -133,6 +133,7 @@ pub mod owned; pub mod managed; pub mod borrow; pub mod rc; +pub mod gc; /* Core language traits */