about summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-04-01 22:41:08 +0000
committerbors <bors@rust-lang.org>2015-04-01 22:41:08 +0000
commit2e3b0c051dca9880bf66b5366dccd2e0bb424b99 (patch)
tree2e8b8ea5a0daf51f819acaab9b9e2572459e2a60 /src/liballoc
parentd528aa9960cb9b937d8ef6c09905a6a8076d5f3a (diff)
parent0304e15e5c39654346e827c2bb25ca41ed310c86 (diff)
downloadrust-2e3b0c051dca9880bf66b5366dccd2e0bb424b99.tar.gz
rust-2e3b0c051dca9880bf66b5366dccd2e0bb424b99.zip
Auto merge of #23955 - alexcrichton:rollup, r=alexcrichton
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/arc.rs59
-rw-r--r--src/liballoc/boxed.rs114
-rw-r--r--src/liballoc/boxed_test.rs8
-rw-r--r--src/liballoc/lib.rs2
4 files changed, 124 insertions, 59 deletions
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 855c86f08e7..f87c450eda5 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -242,6 +242,41 @@ pub fn weak_count<T>(this: &Arc<T>) -> usize { this.inner().weak.load(SeqCst) -
 #[unstable(feature = "alloc")]
 pub fn strong_count<T>(this: &Arc<T>) -> usize { this.inner().strong.load(SeqCst) }
 
+
+/// Try accessing a mutable reference to the contents behind an unique `Arc<T>`.
+///
+/// The access is granted only if this is the only reference to the object.
+/// Otherwise, `None` is returned.
+///
+/// # Examples
+///
+/// ```
+/// # #![feature(alloc)]
+/// extern crate alloc;
+/// # fn main() {
+/// use alloc::arc;
+///
+/// let mut four = arc::Arc::new(4);
+///
+/// arc::unique(&mut four).map(|num| *num = 5);
+/// # }
+/// ```
+#[inline]
+#[unstable(feature = "alloc")]
+pub fn unique<T>(this: &mut Arc<T>) -> Option<&mut T> {
+    if strong_count(this) == 1 && weak_count(this) == 0 {
+        // This unsafety is ok because we're guaranteed that the pointer
+        // returned is the *only* pointer that will ever be returned to T. Our
+        // reference count is guaranteed to be 1 at this point, and we required
+        // the Arc itself to be `mut`, so we're returning the only possible
+        // reference to the inner data.
+        let inner = unsafe { &mut **this._ptr };
+        Some(&mut inner.data)
+    }else {
+        None
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Arc<T> {
     /// Makes a clone of the `Arc<T>`.
@@ -312,11 +347,8 @@ impl<T: Send + Sync + Clone> Arc<T> {
            self.inner().weak.load(SeqCst) != 1 {
             *self = Arc::new((**self).clone())
         }
-        // This unsafety is ok because we're guaranteed that the pointer
-        // returned is the *only* pointer that will ever be returned to T. Our
-        // reference count is guaranteed to be 1 at this point, and we required
-        // the Arc itself to be `mut`, so we're returning the only possible
-        // reference to the inner data.
+        // As with `unique()`, the unsafety is ok because our reference was
+        // either unique to begin with, or became one upon cloning the contents.
         let inner = unsafe { &mut **self._ptr };
         &mut inner.data
     }
@@ -659,7 +691,7 @@ mod tests {
     use std::sync::atomic::Ordering::{Acquire, SeqCst};
     use std::thread;
     use std::vec::Vec;
-    use super::{Arc, Weak, weak_count, strong_count};
+    use super::{Arc, Weak, weak_count, strong_count, unique};
     use std::sync::Mutex;
 
     struct Canary(*mut atomic::AtomicUsize);
@@ -696,6 +728,21 @@ mod tests {
     }
 
     #[test]
+    fn test_arc_unique() {
+        let mut x = Arc::new(10);
+        assert!(unique(&mut x).is_some());
+        {
+            let y = x.clone();
+            assert!(unique(&mut x).is_none());
+        }
+        {
+            let z = x.downgrade();
+            assert!(unique(&mut x).is_none());
+        }
+        assert!(unique(&mut x).is_some());
+    }
+
+    #[test]
     fn test_cowarc_clone_make_unique() {
         let mut cow0 = Arc::new(75);
         let mut cow1 = cow0.clone();
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 550b25ac3a7..2801cf38cb7 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -51,15 +51,12 @@ use core::prelude::*;
 use core::any::Any;
 use core::cmp::Ordering;
 use core::default::Default;
-use core::error::Error;
 use core::fmt;
 use core::hash::{self, Hash};
 use core::mem;
 use core::ops::{Deref, DerefMut};
-use core::ptr::{self, Unique};
-use core::raw::{TraitObject, Slice};
-
-use heap;
+use core::ptr::{Unique};
+use core::raw::{TraitObject};
 
 /// A value that represents the heap. This is the default place that the `box`
 /// keyword allocates into when no place is supplied.
@@ -86,6 +83,7 @@ pub static HEAP: () = ();
 /// See the [module-level documentation](../../std/boxed/index.html) for more.
 #[lang = "owned_box"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[fundamental]
 pub struct Box<T>(Unique<T>);
 
 impl<T> Box<T> {
@@ -278,13 +276,6 @@ impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Box<Any> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("Box<Any>")
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Deref for Box<T> {
     type Target = T;
 
@@ -309,49 +300,74 @@ impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
-    fn from(err: E) -> Box<Error + 'a> {
-        Box::new(err)
+
+/// `FnBox` is a version of the `FnOnce` intended for use with boxed
+/// closure objects. The idea is that where one would normally store a
+/// `Box<FnOnce()>` in a data structure, you should use
+/// `Box<FnBox()>`. The two traits behave essentially the same, except
+/// that a `FnBox` closure can only be called if it is boxed. (Note
+/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
+/// closures become directly usable.)
+///
+/// ### Example
+///
+/// Here is a snippet of code which creates a hashmap full of boxed
+/// once closures and then removes them one by one, calling each
+/// closure as it is removed. Note that the type of the closures
+/// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce()
+/// -> i32>`.
+///
+/// ```
+/// #![feature(core)]
+///
+/// use std::boxed::FnBox;
+/// use std::collections::HashMap;
+///
+/// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> {
+///     let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new();
+///     map.insert(1, Box::new(|| 22));
+///     map.insert(2, Box::new(|| 44));
+///     map
+/// }
+///
+/// fn main() {
+///     let mut map = make_map();
+///     for i in &[1, 2] {
+///         let f = map.remove(&i).unwrap();
+///         assert_eq!(f(), i * 22);
+///     }
+/// }
+/// ```
+#[rustc_paren_sugar]
+#[unstable(feature = "core", reason = "Newly introduced")]
+pub trait FnBox<A> {
+    type Output;
+
+    fn call_box(self: Box<Self>, args: A) -> Self::Output;
+}
+
+impl<A,F> FnBox<A> for F
+    where F: FnOnce<A>
+{
+    type Output = F::Output;
+
+    fn call_box(self: Box<F>, args: A) -> F::Output {
+        self.call_once(args)
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, E: Error + Send + 'a> From<E> for Box<Error + Send + 'a> {
-    fn from(err: E) -> Box<Error + Send + 'a> {
-        Box::new(err)
+impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+'a> {
+    type Output = R;
+
+    extern "rust-call" fn call_once(self, args: A) -> R {
+        self.call_box(args)
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b> From<&'b str> for Box<Error + Send + 'a> {
-    fn from(err: &'b str) -> Box<Error + Send + 'a> {
-        #[derive(Debug)]
-        struct StringError(Box<str>);
-        impl Error for StringError {
-            fn description(&self) -> &str { &self.0 }
-        }
-        impl fmt::Display for StringError {
-            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-                self.0.fmt(f)
-            }
-        }
+impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
+    type Output = R;
 
-        // Unfortunately `String` is located in libcollections, so we construct
-        // a `Box<str>` manually here.
-        unsafe {
-            let alloc = if err.len() == 0 {
-                0 as *mut u8
-            } else {
-                let ptr = heap::allocate(err.len(), 1);
-                if ptr.is_null() { ::oom(); }
-                ptr as *mut u8
-            };
-            ptr::copy(err.as_bytes().as_ptr(), alloc, err.len());
-            Box::new(StringError(mem::transmute(Slice {
-                data: alloc,
-                len: err.len(),
-            })))
-        }
+    extern "rust-call" fn call_once(self, args: A) -> R {
+        self.call_box(args)
     }
 }
diff --git a/src/liballoc/boxed_test.rs b/src/liballoc/boxed_test.rs
index 682d5f407c4..fc44ac4eac6 100644
--- a/src/liballoc/boxed_test.rs
+++ b/src/liballoc/boxed_test.rs
@@ -55,17 +55,17 @@ fn test_show() {
     let b = Box::new(Test) as Box<Any>;
     let a_str = format!("{:?}", a);
     let b_str = format!("{:?}", b);
-    assert_eq!(a_str, "Box<Any>");
-    assert_eq!(b_str, "Box<Any>");
+    assert_eq!(a_str, "Any");
+    assert_eq!(b_str, "Any");
 
     static EIGHT: usize = 8;
     static TEST: Test = Test;
     let a = &EIGHT as &Any;
     let b = &TEST as &Any;
     let s = format!("{:?}", a);
-    assert_eq!(s, "&Any");
+    assert_eq!(s, "Any");
     let s = format!("{:?}", b);
-    assert_eq!(s, "&Any");
+    assert_eq!(s, "Any");
 }
 
 #[test]
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index b92dfa9117e..a8be63d6373 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -71,6 +71,8 @@
 #![feature(no_std)]
 #![no_std]
 #![feature(allocator)]
+#![feature(custom_attribute)]
+#![feature(fundamental)]
 #![feature(lang_items, unsafe_destructor)]
 #![feature(box_syntax)]
 #![feature(optin_builtin_traits)]