prototype Placer protocol for unstable overloaded-box and placement-in.
This commit is contained in:
@@ -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};
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user