diff options
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/boxed.rs | 109 | ||||
| -rw-r--r-- | src/liballoc/lib.rs | 4 |
2 files changed, 107 insertions, 6 deletions
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index d9653cecc73..acf22094233 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -55,13 +55,16 @@ use core::prelude::*; +use heap; + use core::any::Any; use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash}; -use core::marker::Unsize; +use core::marker::{self, Unsize}; use core::mem; use core::ops::{CoerceUnsized, Deref, DerefMut}; +use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace}; use core::ptr::Unique; use core::raw::{TraitObject}; @@ -72,7 +75,7 @@ use core::raw::{TraitObject}; /// /// ``` /// # #![feature(box_heap)] -/// #![feature(box_syntax)] +/// #![feature(box_syntax, placement_in_syntax)] /// use std::boxed::HEAP; /// /// fn main() { @@ -83,7 +86,12 @@ use core::raw::{TraitObject}; #[lang = "exchange_heap"] #[unstable(feature = "box_heap", reason = "may be renamed; uncertain about custom allocator design")] -pub const HEAP: () = (); +pub const HEAP: ExchangeHeapSingleton = + ExchangeHeapSingleton { _force_singleton: () }; + +/// This the singleton type used solely for `boxed::HEAP`. +#[derive(Copy, Clone)] +pub struct ExchangeHeapSingleton { _force_singleton: () } /// A pointer type for heap allocation. /// @@ -91,7 +99,97 @@ pub const HEAP: () = (); #[lang = "owned_box"] #[stable(feature = "rust1", since = "1.0.0")] #[fundamental] -pub struct Box<T>(Unique<T>); +pub struct Box<T: ?Sized>(Unique<T>); + +/// `IntermediateBox` represents uninitialized backing storage for `Box`. +/// +/// FIXME (pnkfelix): Ideally we would just reuse `Box<T>` instead of +/// introducing a separate `IntermediateBox<T>`; but then you hit +/// issues when you e.g. attempt to destructure an instance of `Box`, +/// since it is a lang item and so it gets special handling by the +/// compiler. Easier just to make this parallel type for now. +/// +/// FIXME (pnkfelix): Currently the `box` protocol only supports +/// creating instances of sized types. This IntermediateBox is +/// designed to be forward-compatible with a future protocol that +/// supports creating instances of unsized types; that is why the type +/// parameter has the `?Sized` generalization marker, and is also why +/// this carries an explicit size. However, it probably does not need +/// to carry the explicit alignment; that is just a work-around for +/// the fact that the `align_of` intrinsic currently requires the +/// input type to be Sized (which I do not think is strictly +/// necessary). +#[unstable(feature = "placement_in", reason = "placement box design is still being worked out.")] +pub struct IntermediateBox<T: ?Sized>{ + ptr: *mut u8, + size: usize, + align: usize, + marker: marker::PhantomData<*mut T>, +} + +impl<T> Place<T> for IntermediateBox<T> { + fn pointer(&mut self) -> *mut T { + unsafe { ::core::mem::transmute(self.ptr) } + } +} + +unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> { + let p = b.ptr as *mut T; + mem::forget(b); + mem::transmute(p) +} + +fn make_place<T>() -> IntermediateBox<T> { + let size = mem::size_of::<T>(); + let align = mem::align_of::<T>(); + + let p = if size == 0 { + heap::EMPTY as *mut u8 + } else { + let p = unsafe { + heap::allocate(size, align) + }; + if p.is_null() { + panic!("Box make_place allocation failure."); + } + p + }; + + IntermediateBox { ptr: p, size: size, align: align, marker: marker::PhantomData } +} + +impl<T> BoxPlace<T> for IntermediateBox<T> { + fn make_place() -> IntermediateBox<T> { make_place() } +} + +impl<T> InPlace<T> for IntermediateBox<T> { + type Owner = Box<T>; + unsafe fn finalize(self) -> Box<T> { finalize(self) } +} + +impl<T> Boxed for Box<T> { + type Data = T; + type Place = IntermediateBox<T>; + unsafe fn finalize(b: IntermediateBox<T>) -> Box<T> { finalize(b) } +} + +impl<T> Placer<T> for ExchangeHeapSingleton { + type Place = IntermediateBox<T>; + + fn make_place(self) -> IntermediateBox<T> { + make_place() + } +} + +impl<T: ?Sized> Drop for IntermediateBox<T> { + fn drop(&mut self) { + if self.size > 0 { + unsafe { + heap::deallocate(self.ptr, self.size, self.align) + } + } + } +} impl<T> Box<T> { /// Allocates memory on the heap and then moves `x` into it. @@ -199,8 +297,7 @@ impl<T: Clone> Clone for Box<T> { /// let y = x.clone(); /// ``` #[inline] - fn clone(&self) -> Box<T> { box {(**self).clone()} } - + fn clone(&self) -> Box<T> { box (HEAP) {(**self).clone()} } /// Copies `source`'s contents into `self` without creating a new allocation. /// /// # Examples diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ead0b4259a9..f66495c4057 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -70,6 +70,8 @@ test(no_crate_inject))] #![no_std] +// SNAP d4432b3 +#![allow(unused_features)] // until feature(placement_in_syntax) is in snap #![feature(allocator)] #![feature(box_syntax)] #![feature(coerce_unsized)] @@ -82,6 +84,8 @@ #![feature(no_std)] #![feature(nonzero)] #![feature(optin_builtin_traits)] +#![feature(placement_in_syntax)] +#![feature(placement_new_protocol)] #![feature(raw)] #![feature(staged_api)] #![feature(unboxed_closures)] |
