Skip to content

Commit

Permalink
Merge pull request rust-lang#31 from Mark-Simulacrum/update-allocators
Browse files Browse the repository at this point in the history
Update to use the new allocator APIs.
  • Loading branch information
alexcrichton authored Jul 10, 2017
2 parents 794c2d6 + 56d90fa commit eee5ffb
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 53 deletions.
43 changes: 12 additions & 31 deletions src/destructors.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,19 @@ this is totally fine.
For instance, a custom implementation of `Box` might write `Drop` like this:

```rust
#![feature(alloc, heap_api, unique)]
#![feature(unique, allocator_api)]

extern crate alloc;

use std::ptr::{drop_in_place, Unique};
use std::heap::{Heap, Alloc, Layout};
use std::mem;

use alloc::heap;
use std::ptr::{drop_in_place, Unique};

struct Box<T>{ ptr: Unique<T> }

impl<T> Drop for Box<T> {
fn drop(&mut self) {
unsafe {
drop_in_place(self.ptr.as_ptr());
heap::deallocate(self.ptr.as_ptr() as *mut u8,
mem::size_of::<T>(),
mem::align_of::<T>());
Heap.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::<T>())
}
}
}
Expand All @@ -57,24 +52,19 @@ use-after-free the `ptr` because when drop exits, it becomes inaccessible.
However this wouldn't work:

```rust
#![feature(alloc, heap_api, unique)]

extern crate alloc;
#![feature(allocator_api, unique)]

use std::heap::{Heap, Alloc, Layout};
use std::ptr::{drop_in_place, Unique};
use std::mem;

use alloc::heap;

struct Box<T>{ ptr: Unique<T> }

impl<T> Drop for Box<T> {
fn drop(&mut self) {
unsafe {
drop_in_place(self.ptr.as_ptr());
heap::deallocate(self.ptr.as_ptr() as *mut u8,
mem::size_of::<T>(),
mem::align_of::<T>());
Heap.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::<T>());
}
}
}
Expand All @@ -86,9 +76,7 @@ impl<T> Drop for SuperBox<T> {
unsafe {
// Hyper-optimized: deallocate the box's contents for it
// without `drop`ing the contents
heap::deallocate(self.my_box.ptr.as_ptr() as *mut u8,
mem::size_of::<T>(),
mem::align_of::<T>());
Heap.dealloc(self.my_box.ptr.as_ptr() as *mut u8, Layout::new::<T>());
}
}
}
Expand Down Expand Up @@ -135,24 +123,19 @@ The classic safe solution to overriding recursive drop and allowing moving out
of Self during `drop` is to use an Option:

```rust
#![feature(alloc, heap_api, unique)]

extern crate alloc;
#![feature(allocator_api, unique)]

use std::heap::{Alloc, Heap, Layout};
use std::ptr::{drop_in_place, Unique};
use std::mem;

use alloc::heap;

struct Box<T>{ ptr: Unique<T> }

impl<T> Drop for Box<T> {
fn drop(&mut self) {
unsafe {
drop_in_place(self.ptr.as_ptr());
heap::deallocate(self.ptr.as_ptr() as *mut u8,
mem::size_of::<T>(),
mem::align_of::<T>());
Heap.dealloc(self.ptr.as_ptr() as *mut u8, Layout::new::<T>());
}
}
}
Expand All @@ -166,9 +149,7 @@ impl<T> Drop for SuperBox<T> {
// without `drop`ing the contents. Need to set the `box`
// field as `None` to prevent Rust from trying to Drop it.
let my_box = self.my_box.take().unwrap();
heap::deallocate(my_box.ptr.as_ptr() as *mut u8,
mem::size_of::<T>(),
mem::align_of::<T>());
Heap.dealloc(my_box.ptr.as_ptr() as *mut u8, Layout::new::<T>());
mem::forget(my_box);
}
}
Expand Down
35 changes: 13 additions & 22 deletions src/vec-final.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@

```rust
#![feature(unique)]
#![feature(alloc, heap_api)]

extern crate alloc;
#![feature(allocator_api)]

use std::ptr::{Unique, self};
use std::mem;
use std::ops::{Deref, DerefMut};
use std::marker::PhantomData;

use alloc::heap;
use std::heap::{Alloc, Layout, Heap};

struct RawVec<T> {
ptr: Unique<T>,
Expand All @@ -35,22 +32,22 @@ impl<T> RawVec<T> {
// 0, getting to here necessarily means the Vec is overfull.
assert!(elem_size != 0, "capacity overflow");

let align = mem::align_of::<T>();

let (new_cap, ptr) = if self.cap == 0 {
let ptr = heap::allocate(elem_size, align);
let ptr = Heap.alloc(Layout::array::<T>(1).unwrap());
(1, ptr)
} else {
let new_cap = 2 * self.cap;
let ptr = heap::reallocate(self.ptr.as_ptr() as *mut _,
self.cap * elem_size,
new_cap * elem_size,
align);
let ptr = Heap.realloc(self.ptr.as_ptr() as *mut _,
Layout::array::<T>(self.cap).unwrap(),
Layout::array::<T>(new_cap).unwrap());
(new_cap, ptr)
};

// If allocate or reallocate fail, we'll get `null` back
if ptr.is_null() { oom() }
// If allocate or reallocate fail, oom
let ptr = match ptr {
Ok(ptr) => ptr,
Err(err) => Heap.oom(err),
};

self.ptr = Unique::new(ptr as *mut _);
self.cap = new_cap;
Expand All @@ -62,20 +59,14 @@ impl<T> Drop for RawVec<T> {
fn drop(&mut self) {
let elem_size = mem::size_of::<T>();
if self.cap != 0 && elem_size != 0 {
let align = mem::align_of::<T>();

let num_bytes = elem_size * self.cap;
unsafe {
heap::deallocate(self.ptr.as_ptr() as *mut _, num_bytes, align);
Heap.dealloc(self.ptr.as_ptr() as *mut _,
Layout::array::<T>(self.cap).unwrap());
}
}
}
}





pub struct Vec<T> {
buf: RawVec<T>,
len: usize,
Expand Down

0 comments on commit eee5ffb

Please sign in to comment.