diff options
| author | Djzin <djzin@users.noreply.github.com> | 2017-05-27 14:31:47 +0100 |
|---|---|---|
| committer | Djzin <djzin@users.noreply.github.com> | 2017-05-27 14:31:47 +0100 |
| commit | 74751358e625878306aa193fed788e79aa53d4fa (patch) | |
| tree | 1ba9b336d1ddb45d9f688d69f5bd4ede028db622 /src/liballoc | |
| parent | c6307a2fa55c3d62c06b85b349257a8194093442 (diff) | |
| parent | 3e7908f616745573a11ad7dfad245f12be0069da (diff) | |
| download | rust-74751358e625878306aa193fed788e79aa53d4fa.tar.gz rust-74751358e625878306aa193fed788e79aa53d4fa.zip | |
Merge remote-tracking branch 'upstream/master' into fast-swap
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/arc.rs | 170 | ||||
| -rw-r--r-- | src/liballoc/boxed.rs | 20 | ||||
| -rw-r--r-- | src/liballoc/heap.rs | 46 | ||||
| -rw-r--r-- | src/liballoc/lib.rs | 2 | ||||
| -rw-r--r-- | src/liballoc/raw_vec.rs | 45 | ||||
| -rw-r--r-- | src/liballoc/rc.rs | 192 | ||||
| -rw-r--r-- | src/liballoc/str.rs | 21 |
7 files changed, 297 insertions, 199 deletions
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 38d843263ff..27ecefe043b 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -54,16 +54,33 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// exception. If you need to mutate through an `Arc`, use [`Mutex`][mutex], /// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. /// -/// `Arc` uses atomic operations for reference counting, so `Arc`s can be -/// sent between threads. In other words, `Arc<T>` implements [`Send`] -/// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is -/// that atomic operations are more expensive than ordinary memory accesses. -/// If you are not sharing reference-counted values between threads, consider -/// using [`rc::Rc`][`Rc`] for lower overhead. [`Rc`] is a safe default, because -/// the compiler will catch any attempt to send an [`Rc`] between threads. -/// However, a library might choose `Arc` in order to give library consumers +/// ## Thread Safety +/// +/// Unlike [`Rc<T>`], `Arc<T>` uses atomic operations for its reference +/// counting This means that it is thread-safe. The disadvantage is that +/// atomic operations are more expensive than ordinary memory accesses. If you +/// are not sharing reference-counted values between threads, consider using +/// [`Rc<T>`] for lower overhead. [`Rc<T>`] is a safe default, because the +/// compiler will catch any attempt to send an [`Rc<T>`] between threads. +/// However, a library might choose `Arc<T>` in order to give library consumers /// more flexibility. /// +/// `Arc<T>` will implement [`Send`] and [`Sync`] as long as the `T` implements +/// [`Send`] and [`Sync`]. Why can't you put a non-thread-safe type `T` in an +/// `Arc<T>` to make it thread-safe? This may be a bit counter-intuitive at +/// first: after all, isn't the point of `Arc<T>` thread safety? The key is +/// this: `Arc<T>` makes it thread safe to have multiple ownership of the same +/// data, but it doesn't add thread safety to its data. Consider +/// `Arc<RefCell<T>>`. `RefCell<T>` isn't [`Sync`], and if `Arc<T>` was always +/// [`Send`], `Arc<RefCell<T>>` would be as well. But then we'd have a problem: +/// `RefCell<T>` is not thread safe; it keeps track of the borrowing count using +/// non-atomic operations. +/// +/// In the end, this means that you may need to pair `Arc<T>` with some sort of +/// `std::sync` type, usually `Mutex<T>`. +/// +/// ## Breaking cycles with `Weak` +/// /// The [`downgrade`][downgrade] method can be used to create a non-owning /// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d /// to an `Arc`, but this will return [`None`] if the value has already been @@ -74,6 +91,8 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak] /// pointers from children back to their parents. /// +/// ## `Deref` behavior +/// /// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait), /// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name /// clashes with `T`'s methods, the methods of `Arc<T>` itself are [associated @@ -91,18 +110,18 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// /// [arc]: struct.Arc.html /// [weak]: struct.Weak.html -/// [`Rc`]: ../../std/rc/struct.Rc.html +/// [`Rc<T>`]: ../../std/rc/struct.Rc.html /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone /// [mutex]: ../../std/sync/struct.Mutex.html /// [rwlock]: ../../std/sync/struct.RwLock.html /// [atomic]: ../../std/sync/atomic/index.html /// [`Send`]: ../../std/marker/trait.Send.html -/// [sync]: ../../std/marker/trait.Sync.html +/// [`Sync`]: ../../std/marker/trait.Sync.html /// [deref]: ../../std/ops/trait.Deref.html /// [downgrade]: struct.Arc.html#method.downgrade /// [upgrade]: struct.Weak.html#method.upgrade /// [`None`]: ../../std/option/enum.Option.html#variant.None -/// [assoc]: ../../book/method-syntax.html#associated-functions +/// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions /// /// # Examples /// @@ -165,18 +184,29 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {} #[unstable(feature = "coerce_unsized", issue = "27732")] impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {} -/// A weak version of [`Arc`][arc]. +/// `Weak` is a version of [`Arc`] that holds a non-owning reference to the +/// managed value. The value is accessed by calling [`upgrade`] on the `Weak` +/// pointer, which returns an [`Option`]`<`[`Arc`]`<T>>`. /// -/// `Weak` pointers do not count towards determining if the inner value -/// should be dropped. +/// Since a `Weak` reference does not count towards ownership, it will not +/// prevent the inner value from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present and may return [`None`] +/// when [`upgrade`]d. /// -/// The typical way to obtain a `Weak` pointer is to call -/// [`Arc::downgrade`][downgrade]. +/// A `Weak` pointer is useful for keeping a temporary reference to the value +/// within [`Arc`] without extending its lifetime. It is also used to prevent +/// circular references between [`Arc`] pointers, since mutual owning references +/// would never allow either [`Arc`] to be dropped. For example, a tree could +/// have strong [`Arc`] pointers from parent nodes to children, and `Weak` +/// pointers from children back to their parents. /// -/// See the [`Arc`][arc] documentation for more details. +/// The typical way to obtain a `Weak` pointer is to call [`Arc::downgrade`]. /// -/// [arc]: struct.Arc.html -/// [downgrade]: struct.Arc.html#method.downgrade +/// [`Arc`]: struct.Arc.html +/// [`Arc::downgrade`]: struct.Arc.html#method.downgrade +/// [`upgrade`]: struct.Weak.html#method.upgrade +/// [`Option`]: ../../std/option/enum.Option.html +/// [`None`]: ../../std/option/enum.Option.html#variant.None #[stable(feature = "arc_weak", since = "1.4.0")] pub struct Weak<T: ?Sized> { ptr: Shared<ArcInner<T>>, @@ -266,8 +296,7 @@ impl<T> Arc<T> { atomic::fence(Acquire); unsafe { - let ptr = *this.ptr; - let elem = ptr::read(&(*ptr).data); + let elem = ptr::read(&this.ptr.as_ref().data); // Make a weak pointer to clean up the implicit strong-weak reference let _weak = Weak { ptr: this.ptr }; @@ -287,17 +316,15 @@ impl<T> Arc<T> { /// # Examples /// /// ``` - /// #![feature(rc_raw)] - /// /// use std::sync::Arc; /// /// let x = Arc::new(10); /// let x_ptr = Arc::into_raw(x); /// assert_eq!(unsafe { *x_ptr }, 10); /// ``` - #[unstable(feature = "rc_raw", issue = "37197")] - pub fn into_raw(this: Self) -> *mut T { - let ptr = unsafe { &mut (**this.ptr).data as *mut _ }; + #[stable(feature = "rc_raw", since = "1.17.0")] + pub fn into_raw(this: Self) -> *const T { + let ptr: *const T = &*this; mem::forget(this); ptr } @@ -315,8 +342,6 @@ impl<T> Arc<T> { /// # Examples /// /// ``` - /// #![feature(rc_raw)] - /// /// use std::sync::Arc; /// /// let x = Arc::new(10); @@ -332,11 +357,14 @@ impl<T> Arc<T> { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` - #[unstable(feature = "rc_raw", issue = "37197")] - pub unsafe fn from_raw(ptr: *mut T) -> Self { + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { // To find the corresponding pointer to the `ArcInner` we need to subtract the offset of the // `data` field from the pointer. - Arc { ptr: Shared::new((ptr as *mut u8).offset(-offset_of!(ArcInner<T>, data)) as *mut _) } + let ptr = (ptr as *const u8).offset(-offset_of!(ArcInner<T>, data)); + Arc { + ptr: Shared::new(ptr as *mut u8 as *mut _), + } } } @@ -442,17 +470,17 @@ impl<T: ?Sized> Arc<T> { // `ArcInner` structure itself is `Sync` because the inner data is // `Sync` as well, so we're ok loaning out an immutable pointer to these // contents. - unsafe { &**self.ptr } + unsafe { self.ptr.as_ref() } } // Non-inlined part of `drop`. #[inline(never)] unsafe fn drop_slow(&mut self) { - let ptr = *self.ptr; + let ptr = self.ptr.as_ptr(); // Destroy the data at this time, even though we may not free the box // allocation itself (there may still be weak pointers lying around). - ptr::drop_in_place(&mut (*ptr).data); + ptr::drop_in_place(&mut self.ptr.as_mut().data); if self.inner().weak.fetch_sub(1, Release) == 1 { atomic::fence(Acquire); @@ -461,17 +489,13 @@ impl<T: ?Sized> Arc<T> { } #[inline] - #[unstable(feature = "ptr_eq", - reason = "newly added", - issue = "36497")] + #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns true if the two `Arc`s point to the same value (not /// just values that compare as equal). /// /// # Examples /// /// ``` - /// #![feature(ptr_eq)] - /// /// use std::sync::Arc; /// /// let five = Arc::new(5); @@ -482,9 +506,7 @@ impl<T: ?Sized> Arc<T> { /// assert!(!Arc::ptr_eq(&five, &other_five)); /// ``` pub fn ptr_eq(this: &Self, other: &Self) -> bool { - let this_ptr: *const ArcInner<T> = *this.ptr; - let other_ptr: *const ArcInner<T> = *other.ptr; - this_ptr == other_ptr + this.ptr.as_ptr() == other.ptr.as_ptr() } } @@ -615,7 +637,7 @@ impl<T: Clone> Arc<T> { // here (due to zeroing) because data is no longer accessed by // other threads (due to there being no more strong refs at this // point). - let mut swap = Arc::new(ptr::read(&(**weak.ptr).data)); + let mut swap = Arc::new(ptr::read(&weak.ptr.as_ref().data)); mem::swap(this, &mut swap); mem::forget(swap); } @@ -628,8 +650,7 @@ impl<T: Clone> Arc<T> { // As with `get_mut()`, the unsafety is ok because our reference was // either unique to begin with, or became one upon cloning the contents. unsafe { - let inner = &mut **this.ptr; - &mut inner.data + &mut this.ptr.as_mut().data } } } @@ -671,8 +692,7 @@ impl<T: ?Sized> Arc<T> { // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. unsafe { - let inner = &mut **this.ptr; - Some(&mut inner.data) + Some(&mut this.ptr.as_mut().data) } } else { None @@ -761,7 +781,18 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> { // > through this reference must obviously happened before), and an // > "acquire" operation before deleting the object. // + // In particular, while the contents of an Arc are usually immutable, it's + // possible to have interior writes to something like a Mutex<T>. Since a + // Mutex is not acquired when it is deleted, we can't rely on its + // synchronization logic to make writes in thread A visible to a destructor + // running in thread B. + // + // Also note that the Acquire fence here could probably be replaced with an + // Acquire load, which could improve performance in highly-contended + // situations. See [2]. + // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + // [2]: (https://github.com/rust-lang/rust/pull/41714) atomic::fence(Acquire); unsafe { @@ -771,14 +802,11 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc<T> { } impl<T> Weak<T> { - /// Constructs a new `Weak<T>`, without an accompanying instance of `T`. + /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing + /// it. Calling [`upgrade`] on the return value always gives [`None`]. /// - /// This allocates memory for `T`, but does not initialize it. Calling - /// [`upgrade`][upgrade] on the return value always gives - /// [`None`][option]. - /// - /// [upgrade]: struct.Weak.html#method.upgrade - /// [option]: ../../std/option/enum.Option.html + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -803,13 +831,13 @@ impl<T> Weak<T> { } impl<T: ?Sized> Weak<T> { - /// Upgrades the `Weak` pointer to an [`Arc`][arc], if possible. + /// Attempts to upgrade the `Weak` pointer to an [`Arc`], extending + /// the lifetime of the value if successful. /// - /// Returns [`None`][option] if the strong count has reached zero and the - /// inner value was destroyed. + /// Returns [`None`] if the value has since been dropped. /// - /// [arc]: struct.Arc.html - /// [option]: ../../std/option/enum.Option.html + /// [`Arc`]: struct.Arc.html + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -864,16 +892,13 @@ impl<T: ?Sized> Weak<T> { #[inline] fn inner(&self) -> &ArcInner<T> { // See comments above for why this is "safe" - unsafe { &**self.ptr } + unsafe { self.ptr.as_ref() } } } #[stable(feature = "arc_weak", since = "1.4.0")] impl<T: ?Sized> Clone for Weak<T> { - /// Makes a clone of the `Weak` pointer. - /// - /// This creates another pointer to the same inner value, increasing the - /// weak reference count. + /// Makes a clone of the `Weak` pointer that points to the same value. /// /// # Examples /// @@ -905,14 +930,11 @@ impl<T: ?Sized> Clone for Weak<T> { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl<T> Default for Weak<T> { - /// Constructs a new `Weak<T>`, without an accompanying instance of `T`. + /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing + /// it. Calling [`upgrade`] on the return value always gives [`None`]. /// - /// This allocates memory for `T`, but does not initialize it. Calling - /// [`upgrade`][upgrade] on the return value always gives - /// [`None`][option]. - /// - /// [upgrade]: struct.Weak.html#method.upgrade - /// [option]: ../../std/option/enum.Option.html + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -931,8 +953,6 @@ impl<T> Default for Weak<T> { impl<T: ?Sized> Drop for Weak<T> { /// Drops the `Weak` pointer. /// - /// This will decrement the weak reference count. - /// /// # Examples /// /// ``` @@ -956,7 +976,7 @@ impl<T: ?Sized> Drop for Weak<T> { /// assert!(other_weak_foo.upgrade().is_none()); /// ``` fn drop(&mut self) { - let ptr = *self.ptr; + let ptr = self.ptr.as_ptr(); // If we find out that we were the last weak pointer, then its time to // deallocate the data entirely. See the discussion in Arc::drop() about @@ -1137,7 +1157,7 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Arc<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> fmt::Pointer for Arc<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Pointer::fmt(&*self.ptr, f) + fmt::Pointer::fmt(&self.ptr, f) } } diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 43b0d72186a..8a39be8fae8 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -68,6 +68,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut}; use core::ops::{BoxPlace, Boxed, InPlace, Place, Placer}; use core::ptr::{self, Unique}; use core::convert::From; +use str::from_boxed_utf8_unchecked; /// A value that represents the heap. This is the default place that the `box` /// keyword allocates into when no place is supplied. @@ -155,7 +156,7 @@ fn make_place<T>() -> IntermediateBox<T> { let align = mem::align_of::<T>(); let p = if size == 0 { - heap::EMPTY as *mut u8 + mem::align_of::<T>() as *mut u8 } else { let p = unsafe { heap::allocate(size, align) }; if p.is_null() { @@ -320,8 +321,7 @@ impl<T> Default for Box<[T]> { #[stable(feature = "default_box_extra", since = "1.17.0")] impl Default for Box<str> { fn default() -> Box<str> { - let default: Box<[u8]> = Default::default(); - unsafe { mem::transmute(default) } + unsafe { from_boxed_utf8_unchecked(Default::default()) } } } @@ -366,7 +366,7 @@ impl Clone for Box<str> { let buf = RawVec::with_capacity(len); unsafe { ptr::copy_nonoverlapping(self.as_ptr(), buf.ptr(), len); - mem::transmute(buf.into_box()) // bytes to str ~magic + from_boxed_utf8_unchecked(buf.into_box()) } } } @@ -441,8 +441,16 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { #[stable(feature = "box_from_slice", since = "1.17.0")] impl<'a> From<&'a str> for Box<str> { fn from(s: &'a str) -> Box<str> { - let boxed: Box<[u8]> = Box::from(s.as_bytes()); - unsafe { mem::transmute(boxed) } + unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } + } +} + +#[stable(feature = "boxed_str_conv", since = "1.19.0")] +impl From<Box<str>> for Box<[u8]> { + fn from(s: Box<str>) -> Self { + unsafe { + mem::transmute(s) + } } } diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 51e6f2f8bd7..5ff21c86483 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -16,13 +16,13 @@ issue = "27700")] use core::{isize, usize}; -#[cfg(not(test))] use core::intrinsics::{min_align_of_val, size_of_val}; #[allow(improper_ctypes)] extern "C" { #[allocator] fn __rust_allocate(size: usize, align: usize) -> *mut u8; + fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8; fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize); fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8; fn __rust_reallocate_inplace(ptr: *mut u8, @@ -59,6 +59,20 @@ pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 { __rust_allocate(size, align) } +/// Return a pointer to `size` bytes of memory aligned to `align` and +/// initialized to zeroes. +/// +/// On failure, return a null pointer. +/// +/// Behavior is undefined if the requested size is 0 or the alignment is not a +/// power of 2. The alignment must be no larger than the largest supported page +/// size on the platform. +#[inline] +pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 { + check_size_and_alignment(size, align); + __rust_allocate_zeroed(size, align) +} + /// Resize the allocation referenced by `ptr` to `size` bytes. /// /// On failure, return a null pointer and leave the original allocation intact. @@ -124,7 +138,9 @@ pub fn usable_size(size: usize, align: usize) -> usize { /// /// This preserves the non-null invariant for types like `Box<T>`. The address /// may overlap with non-zero-size memory allocations. -pub const EMPTY: *mut () = 0x1 as *mut (); +#[rustc_deprecated(since = "1.19", reason = "Use Unique/Shared::empty() instead")] +#[unstable(feature = "heap_api", issue = "27700")] +pub const EMPTY: *mut () = 1 as *mut (); /// The allocator for unique pointers. // This function must not unwind. If it does, MIR trans will fail. @@ -133,7 +149,7 @@ pub const EMPTY: *mut () = 0x1 as *mut (); #[inline] unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { if size == 0 { - EMPTY as *mut u8 + align as *mut u8 } else { let ptr = allocate(size, align); if ptr.is_null() { @@ -143,10 +159,9 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { } } -#[cfg(not(test))] -#[lang = "box_free"] +#[cfg_attr(not(test), lang = "box_free")] #[inline] -unsafe fn box_free<T: ?Sized>(ptr: *mut T) { +pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) { let size = size_of_val(&*ptr); let align = min_align_of_val(&*ptr); // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary. @@ -163,6 +178,25 @@ mod tests { use heap; #[test] + fn allocate_zeroed() { + unsafe { + let size = 1024; + let ptr = heap::allocate_zeroed(size, 1); + if ptr.is_null() { + ::oom() + } + + let end = ptr.offset(size as isize); + let mut i = ptr; + while i < end { + assert_eq!(*i, 0); + i = i.offset(1); + } + heap::deallocate(ptr, size, 1); + } + } + + #[test] fn basic_reallocate_inplace_noop() { unsafe { let size = 4000; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 0c01eabd593..418a084da67 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -128,6 +128,8 @@ mod boxed_test; pub mod arc; pub mod rc; pub mod raw_vec; +#[unstable(feature = "str_box_extras", issue = "41119")] +pub mod str; pub mod oom; pub use oom::oom; diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 357a2724e00..7edf07944ec 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -22,13 +22,13 @@ use core::cmp; /// involved. This type is excellent for building your own data structures like Vec and VecDeque. /// In particular: /// -/// * Produces heap::EMPTY on zero-sized types -/// * Produces heap::EMPTY on zero-length allocations +/// * Produces Unique::empty() on zero-sized types +/// * Produces Unique::empty() on zero-length allocations /// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics) /// * Guards against 32-bit systems allocating more than isize::MAX bytes /// * Guards against overflowing your length /// * Aborts on OOM -/// * Avoids freeing heap::EMPTY +/// * Avoids freeing Unique::empty() /// * Contains a ptr::Unique and thus endows the user with all related benefits /// /// This type does not in anyway inspect the memory that it manages. When dropped it *will* @@ -55,15 +55,13 @@ impl<T> RawVec<T> { /// it makes a RawVec with capacity `usize::MAX`. Useful for implementing /// delayed allocation. pub fn new() -> Self { - unsafe { - // !0 is usize::MAX. This branch should be stripped at compile time. - let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 }; + // !0 is usize::MAX. This branch should be stripped at compile time. + let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 }; - // heap::EMPTY doubles as "unallocated" and "zero-sized allocation" - RawVec { - ptr: Unique::new(heap::EMPTY as *mut T), - cap: cap, - } + // Unique::empty() doubles as "unallocated" and "zero-sized allocation" + RawVec { + ptr: Unique::empty(), + cap: cap, } } @@ -81,7 +79,18 @@ impl<T> RawVec<T> { /// # Aborts /// /// Aborts on OOM + #[inline] pub fn with_capacity(cap: usize) -> Self { + RawVec::allocate(cap, false) + } + + /// Like `with_capacity` but guarantees the buffer is zeroed. + #[inline] + pub fn with_capacity_zeroed(cap: usize) -> Self { + RawVec::allocate(cap, true) + } + + fn allocate(cap: usize, zeroed: bool) -> Self { unsafe { let elem_size = mem::size_of::<T>(); @@ -90,10 +99,14 @@ impl<T> RawVec<T> { // handles ZSTs and `cap = 0` alike let ptr = if alloc_size == 0 { - heap::EMPTY as *mut u8 + mem::align_of::<T>() as *mut u8 } else { let align = mem::align_of::<T>(); - let ptr = heap::allocate(alloc_size, align); + let ptr = if zeroed { + heap::allocate_zeroed(alloc_size, align) + } else { + heap::allocate(alloc_size, align) + }; if ptr.is_null() { oom() } @@ -133,10 +146,10 @@ impl<T> RawVec<T> { impl<T> RawVec<T> { /// Gets a raw pointer to the start of the allocation. Note that this is - /// heap::EMPTY if `cap = 0` or T is zero-sized. In the former case, you must + /// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must /// be careful. pub fn ptr(&self) -> *mut T { - *self.ptr + self.ptr.as_ptr() } /// Gets the capacity of the allocation. @@ -548,7 +561,7 @@ unsafe impl<#[may_dangle] T> Drop for RawVec<T> { let num_bytes = elem_size * self.cap; unsafe { - heap::deallocate(*self.ptr as *mut _, num_bytes, align); + heap::deallocate(self.ptr() as *mut u8, num_bytes, align); } } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 6108a06634b..d6dbf77bfac 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -13,7 +13,7 @@ //! Single-threaded reference-counting pointers. //! //! The type [`Rc<T>`][`Rc`] provides shared ownership of a value of type `T`, -//! allocated in the heap. Invoking [`clone()`][clone] on [`Rc`] produces a new +//! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new //! pointer to the same value in the heap. When the last [`Rc`] pointer to a //! given value is destroyed, the pointed-to value is also destroyed. //! @@ -30,7 +30,7 @@ //! threads. If you need multi-threaded, atomic reference counting, use //! [`sync::Arc`][arc]. //! -//! The [`downgrade()`][downgrade] method can be used to create a non-owning +//! The [`downgrade`][downgrade] method can be used to create a non-owning //! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d //! to an [`Rc`], but this will return [`None`] if the value has //! already been dropped. @@ -215,7 +215,7 @@ //! [downgrade]: struct.Rc.html#method.downgrade //! [upgrade]: struct.Weak.html#method.upgrade //! [`None`]: ../../std/option/enum.Option.html#variant.None -//! [assoc]: ../../book/method-syntax.html#associated-functions +//! [assoc]: ../../book/first-edition/method-syntax.html#associated-functions //! [mutability]: ../../std/cell/index.html#introducing-mutability-inside-of-something-immutable #![stable(feature = "rust1", since = "1.0.0")] @@ -230,7 +230,7 @@ use core::cell::Cell; use core::cmp::Ordering; use core::fmt; use core::hash::{Hash, Hasher}; -use core::intrinsics::{abort, assume}; +use core::intrinsics::abort; use core::marker; use core::marker::Unsize; use core::mem::{self, align_of_val, forget, size_of, size_of_val, uninitialized}; @@ -239,7 +239,7 @@ use core::ops::CoerceUnsized; use core::ptr::{self, Shared}; use core::convert::From; -use heap::deallocate; +use heap::{allocate, deallocate, box_free}; use raw_vec::RawVec; struct RcBox<T: ?Sized> { @@ -248,7 +248,6 @@ struct RcBox<T: ?Sized> { value: T, } - /// A single-threaded reference-counting pointer. /// /// See the [module-level documentation](./index.html) for more details. @@ -341,19 +340,6 @@ impl<T> Rc<T> { } } - /// Checks whether [`Rc::try_unwrap`][try_unwrap] would return - /// [`Ok`]. - /// - /// [try_unwrap]: struct.Rc.html#method.try_unwrap - /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok - #[unstable(feature = "rc_would_unwrap", - reason = "just added for niche usecase", - issue = "28356")] - #[rustc_deprecated(since = "1.15.0", reason = "too niche; use `strong_count` instead")] - pub fn would_unwrap(this: &Self) -> bool { - Rc::strong_count(&this) == 1 - } - /// Consumes the `Rc`, returning the wrapped pointer. /// /// To avoid a memory leak the pointer must be converted back to an `Rc` using @@ -364,17 +350,15 @@ impl<T> Rc<T> { /// # Examples /// /// ``` - /// #![feature(rc_raw)] - /// /// use std::rc::Rc; /// /// let x = Rc::new(10); /// let x_ptr = Rc::into_raw(x); /// assert_eq!(unsafe { *x_ptr }, 10); /// ``` - #[unstable(feature = "rc_raw", issue = "37197")] - pub fn into_raw(this: Self) -> *mut T { - let ptr = unsafe { &mut (**this.ptr).value as *mut _ }; + #[stable(feature = "rc_raw", since = "1.17.0")] + pub fn into_raw(this: Self) -> *const T { + let ptr: *const T = &*this; mem::forget(this); ptr } @@ -392,8 +376,6 @@ impl<T> Rc<T> { /// # Examples /// /// ``` - /// #![feature(rc_raw)] - /// /// use std::rc::Rc; /// /// let x = Rc::new(10); @@ -409,11 +391,15 @@ impl<T> Rc<T> { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` - #[unstable(feature = "rc_raw", issue = "37197")] - pub unsafe fn from_raw(ptr: *mut T) -> Self { + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { // To find the corresponding pointer to the `RcBox` we need to subtract the offset of the // `value` field from the pointer. - Rc { ptr: Shared::new((ptr as *mut u8).offset(-offset_of!(RcBox<T>, value)) as *mut _) } + + let ptr = (ptr as *const u8).offset(-offset_of!(RcBox<T>, value)); + Rc { + ptr: Shared::new(ptr as *mut u8 as *mut _) + } } } @@ -442,6 +428,38 @@ impl Rc<str> { } } +impl<T> Rc<[T]> { + /// Constructs a new `Rc<[T]>` from a `Box<[T]>`. + #[doc(hidden)] + #[unstable(feature = "rustc_private", + reason = "for internal use in rustc", + issue = "0")] + pub fn __from_array(value: Box<[T]>) -> Rc<[T]> { + unsafe { + let ptr: *mut RcBox<[T]> = + mem::transmute([mem::align_of::<RcBox<[T; 1]>>(), value.len()]); + // FIXME(custom-DST): creating this invalid &[T] is dubiously defined, + // we should have a better way of getting the size/align + // of a DST from its unsized part. + let ptr = allocate(size_of_val(&*ptr), align_of_val(&*ptr)); + let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]); + + // Initialize the new RcBox. + ptr::write(&mut (*ptr).strong, Cell::new(1)); + ptr::write(&mut (*ptr).weak, Cell::new(1)); + ptr::copy_nonoverlapping( + value.as_ptr(), + &mut (*ptr).value as *mut [T] as *mut T, + value.len()); + + // Free the original allocation without freeing its (moved) contents. + box_free(Box::into_raw(value)); + + Rc { ptr: Shared::new(ptr as *mut _) } + } + } +} + impl<T: ?Sized> Rc<T> { /// Creates a new [`Weak`][weak] pointer to this value. /// @@ -505,11 +523,7 @@ impl<T: ?Sized> Rc<T> { /// /// [weak]: struct.Weak.html #[inline] - #[unstable(feature = "is_unique", reason = "uniqueness has unclear meaning", - issue = "28356")] - #[rustc_deprecated(since = "1.15.0", - reason = "too niche; use `strong_count` and `weak_count` instead")] - pub fn is_unique(this: &Self) -> bool { + fn is_unique(this: &Self) -> bool { Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1 } @@ -543,25 +557,22 @@ impl<T: ?Sized> Rc<T> { #[stable(feature = "rc_unique", since = "1.4.0")] pub fn get_mut(this: &mut Self) -> Option<&mut T> { if Rc::is_unique(this) { - let inner = unsafe { &mut **this.ptr }; - Some(&mut inner.value) + unsafe { + Some(&mut this.ptr.as_mut().value) + } } else { None } } #[inline] - #[unstable(feature = "ptr_eq", - reason = "newly added", - issue = "36497")] + #[stable(feature = "ptr_eq", since = "1.17.0")] /// Returns true if the two `Rc`s point to the same value (not /// just values that compare as equal). /// /// # Examples /// /// ``` - /// #![feature(ptr_eq)] - /// /// use std::rc::Rc; /// /// let five = Rc::new(5); @@ -572,9 +583,7 @@ impl<T: ?Sized> Rc<T> { /// assert!(!Rc::ptr_eq(&five, &other_five)); /// ``` pub fn ptr_eq(this: &Self, other: &Self) -> bool { - let this_ptr: *const RcBox<T> = *this.ptr; - let other_ptr: *const RcBox<T> = *other.ptr; - this_ptr == other_ptr + this.ptr.as_ptr() == other.ptr.as_ptr() } } @@ -617,7 +626,7 @@ impl<T: Clone> Rc<T> { } else if Rc::weak_count(this) != 0 { // Can just steal the data, all that's left is Weaks unsafe { - let mut swap = Rc::new(ptr::read(&(**this.ptr).value)); + let mut swap = Rc::new(ptr::read(&this.ptr.as_ref().value)); mem::swap(this, &mut swap); swap.dec_strong(); // Remove implicit strong-weak ref (no need to craft a fake @@ -631,8 +640,9 @@ impl<T: Clone> Rc<T> { // reference count is guaranteed to be 1 at this point, and we required // the `Rc<T>` itself to be `mut`, so we're returning the only possible // reference to the inner value. - let inner = unsafe { &mut **this.ptr }; - &mut inner.value + unsafe { + &mut this.ptr.as_mut().value + } } } @@ -677,12 +687,12 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc<T> { /// ``` fn drop(&mut self) { unsafe { - let ptr = *self.ptr; + let ptr = self.ptr.as_ptr(); self.dec_strong(); if self.strong() == 0 { // destroy the contained object - ptr::drop_in_place(&mut (*ptr).value); + ptr::drop_in_place(self.ptr.as_mut()); // remove the implicit "strong weak" pointer now that we've // destroyed the contents. @@ -919,7 +929,7 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Rc<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> fmt::Pointer for Rc<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Pointer::fmt(&*self.ptr, f) + fmt::Pointer::fmt(&self.ptr, f) } } @@ -930,18 +940,29 @@ impl<T> From<T> for Rc<T> { } } -/// A weak version of [`Rc`][rc]. +/// `Weak` is a version of [`Rc`] that holds a non-owning reference to the +/// managed value. The value is accessed by calling [`upgrade`] on the `Weak` +/// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`. /// -/// `Weak` pointers do not count towards determining if the inner value -/// should be dropped. +/// Since a `Weak` reference does not count towards ownership, it will not +/// prevent the inner value from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present and may return [`None`] +/// when [`upgrade`]d. /// -/// The typical way to obtain a `Weak` pointer is to call -/// [`Rc::downgrade`][downgrade]. +/// A `Weak` pointer is useful for keeping a temporary reference to the value +/// within [`Rc`] without extending its lifetime. It is also used to prevent +/// circular references between [`Rc`] pointers, since mutual owning references +/// would never allow either [`Arc`] to be dropped. For example, a tree could +/// have strong [`Rc`] pointers from parent nodes to children, and `Weak` +/// pointers from children back to their parents. /// -/// See the [module-level documentation](./index.html) for more details. +/// The typical way to obtain a `Weak` pointer is to call [`Rc::downgrade`]. /// -/// [rc]: struct.Rc.html -/// [downgrade]: struct.Rc.html#method.downgrade +/// [`Rc`]: struct.Rc.html +/// [`Rc::downgrade`]: struct.Rc.html#method.downgrade +/// [`upgrade`]: struct.Weak.html#method.upgrade +/// [`Option`]: ../../std/option/enum.Option.html +/// [`None`]: ../../std/option/enum.Option.html#variant.None #[stable(feature = "rc_weak", since = "1.4.0")] pub struct Weak<T: ?Sized> { ptr: Shared<RcBox<T>>, @@ -956,14 +977,11 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {} impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {} impl<T> Weak<T> { - /// Constructs a new `Weak<T>`, without an accompanying instance of `T`. + /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing + /// it. Calling [`upgrade`] on the return value always gives [`None`]. /// - /// This allocates memory for `T`, but does not initialize it. Calling - /// [`upgrade`][upgrade] on the return value always gives - /// [`None`][option]. - /// - /// [upgrade]: struct.Weak.html#method.upgrade - /// [option]: ../../std/option/enum.Option.html + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`None`]: ../../std/option/enum.Option.html /// /// # Examples /// @@ -988,13 +1006,13 @@ impl<T> Weak<T> { } impl<T: ?Sized> Weak<T> { - /// Upgrades the `Weak` pointer to an [`Rc`][rc], if possible. + /// Attempts to upgrade the `Weak` pointer to an [`Rc`], extending + /// the lifetime of the value if successful. /// - /// Returns [`None`][option] if the strong count has reached zero and the - /// inner value was destroyed. + /// Returns [`None`] if the value has since been dropped. /// - /// [rc]: struct.Rc.html - /// [option]: ../../std/option/enum.Option.html + /// [`Rc`]: struct.Rc.html + /// [`None`]: ../../std/option/enum.Option.html /// /// # Examples /// @@ -1029,8 +1047,6 @@ impl<T: ?Sized> Weak<T> { impl<T: ?Sized> Drop for Weak<T> { /// Drops the `Weak` pointer. /// - /// This will decrement the weak reference count. - /// /// # Examples /// /// ``` @@ -1055,7 +1071,7 @@ impl<T: ?Sized> Drop for Weak<T> { /// ``` fn drop(&mut self) { unsafe { - let ptr = *self.ptr; + let ptr = self.ptr.as_ptr(); self.dec_weak(); // the weak count starts at 1, and will only go to zero if all @@ -1069,10 +1085,7 @@ impl<T: ?Sized> Drop for Weak<T> { #[stable(feature = "rc_weak", since = "1.4.0")] impl<T: ?Sized> Clone for Weak<T> { - /// Makes a clone of the `Weak` pointer. - /// - /// This creates another pointer to the same inner value, increasing the - /// weak reference count. + /// Makes a clone of the `Weak` pointer that points to the same value. /// /// # Examples /// @@ -1099,14 +1112,11 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl<T> Default for Weak<T> { - /// Constructs a new `Weak<T>`, without an accompanying instance of `T`. - /// - /// This allocates memory for `T`, but does not initialize it. Calling - /// [`upgrade`][upgrade] on the return value always gives - /// [`None`][option]. + /// Constructs a new `Weak<T>`, allocating memory for `T` without initializing + /// it. Calling [`upgrade`] on the return value always gives [`None`]. /// - /// [upgrade]: struct.Weak.html#method.upgrade - /// [option]: ../../std/option/enum.Option.html + /// [`upgrade`]: struct.Weak.html#method.upgrade + /// [`None`]: ../../std/option/enum.Option.html /// /// # Examples /// @@ -1169,12 +1179,7 @@ impl<T: ?Sized> RcBoxPtr<T> for Rc<T> { #[inline(always)] fn inner(&self) -> &RcBox<T> { unsafe { - // Safe to assume this here, as if it weren't true, we'd be breaking - // the contract anyway. - // This allows the null check to be elided in the destructor if we - // manipulated the reference count in the same function. - assume(!(*(&self.ptr as *const _ as *const *const ())).is_null()); - &(**self.ptr) + self.ptr.as_ref() } } } @@ -1183,12 +1188,7 @@ impl<T: ?Sized> RcBoxPtr<T> for Weak<T> { #[inline(always)] fn inner(&self) -> &RcBox<T> { unsafe { - // Safe to assume this here, as if it weren't true, we'd be breaking - // the contract anyway. - // This allows the null check to be elided in the destructor if we - // manipulated the reference count in the same function. - assume(!(*(&self.ptr as *const _ as *const *const ())).is_null()); - &(**self.ptr) + self.ptr.as_ref() } } } diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs new file mode 100644 index 00000000000..c87db16a0f4 --- /dev/null +++ b/src/liballoc/str.rs @@ -0,0 +1,21 @@ +// Copyright 2012-2017 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Methods for dealing with boxed strings. +use core::mem; + +use boxed::Box; + +/// Converts a boxed slice of bytes to a boxed string slice without checking +/// that the string contains valid UTF-8. +#[unstable(feature = "str_box_extras", issue = "41119")] +pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> { + mem::transmute(v) +} |
