diff options
| author | bors <bors@rust-lang.org> | 2015-04-01 22:41:08 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-04-01 22:41:08 +0000 |
| commit | 2e3b0c051dca9880bf66b5366dccd2e0bb424b99 (patch) | |
| tree | 2e8b8ea5a0daf51f819acaab9b9e2572459e2a60 /src/liballoc | |
| parent | d528aa9960cb9b937d8ef6c09905a6a8076d5f3a (diff) | |
| parent | 0304e15e5c39654346e827c2bb25ca41ed310c86 (diff) | |
| download | rust-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.rs | 59 | ||||
| -rw-r--r-- | src/liballoc/boxed.rs | 114 | ||||
| -rw-r--r-- | src/liballoc/boxed_test.rs | 8 | ||||
| -rw-r--r-- | src/liballoc/lib.rs | 2 |
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)] |
