Skip to content

Commit db04f7d

Browse files
Merge #1
1: Replaced *mut T by Option<NonNull<T>> in box.rs r=kvark a=danielhenrymantilla Co-authored-by: danielhenrymantilla <[email protected]>
2 parents 847426e + 5872f04 commit db04f7d

File tree

3 files changed

+30
-15
lines changed

3 files changed

+30
-15
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Change Log
22

3+
## v0.1.4 (24-06-2019)
4+
- `BoxHelper`: replaced nullable pointer with NonNull
5+
36
## v0.1.3 (31-05-2019)
47
- fixed zero-sized box allocations
58
- fixed file permissions in the package

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "copyless"
33
description = "Ways to eliminate memcpy calls when using the standard library."
4-
version = "0.1.3"
4+
version = "0.1.4"
55
authors = ["Dzmitry Malyshau <[email protected]>"]
66
license = "MPL-2.0"
77
edition = "2018"

src/boxed.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
1-
use std::{alloc, mem, ptr};
1+
use std::{
2+
alloc, mem,
3+
ptr::{self, NonNull},
4+
};
25

36
/// A typesafe helper that stores the allocated pointer without the data initialized.
4-
pub struct BoxAllocation<T>(*mut T);
7+
pub struct BoxAllocation<T>(
8+
// ptr cannot be null since it would mean the allocation failed.
9+
// Note: covariance is acceptable since this eventually becomes a `Box<T>`,
10+
// which is covariant too.
11+
NonNull<T>,
12+
);
513

614
impl<T> BoxAllocation<T> {
715
/// Consumes self and writes the given value into the allocation.
8-
pub fn init(mut self, value: T) -> Box<T> {
16+
#[inline(always)] // if this does not get inlined then copying happens
17+
pub fn init(self, value: T) -> Box<T> {
918
if mem::size_of::<T>() == 0 {
1019
return Box::new(value);
1120
}
1221

13-
let ptr = mem::replace(&mut self.0, ptr::null_mut());
1422
unsafe {
23+
let ptr = self.0.as_ptr();
24+
mem::forget(self);
1525
ptr::write(ptr, value);
1626
Box::from_raw(ptr)
1727
}
@@ -20,16 +30,17 @@ impl<T> BoxAllocation<T> {
2030

2131
impl<T> Drop for BoxAllocation<T> {
2232
fn drop(&mut self) {
23-
if !self.0.is_null() {
24-
let layout = alloc::Layout::new::<T>();
25-
unsafe {
26-
alloc::dealloc(self.0 as *mut u8, layout);
27-
}
33+
if mem::size_of::<T>() == 0 {
34+
return;
35+
}
36+
37+
let layout = alloc::Layout::new::<T>();
38+
unsafe {
39+
alloc::dealloc(self.0.as_ptr() as *mut u8, layout);
2840
}
2941
}
3042
}
3143

32-
3344
/// Helper trait for a `Box` type that allocates up-front.
3445
pub trait BoxHelper<T> {
3546
/// Allocates the storage without providing any data.
@@ -39,12 +50,13 @@ pub trait BoxHelper<T> {
3950
impl<T> BoxHelper<T> for Box<T> {
4051
fn alloc() -> BoxAllocation<T> {
4152
if mem::size_of::<T>() == 0 {
42-
return BoxAllocation(ptr::null_mut());
53+
return BoxAllocation(NonNull::dangling());
4354
}
4455

4556
let layout = alloc::Layout::new::<T>();
46-
BoxAllocation(unsafe {
47-
alloc::alloc(layout) as *mut T
48-
})
57+
BoxAllocation(
58+
NonNull::new(unsafe { alloc::alloc(layout) as *mut T })
59+
.unwrap_or_else(|| alloc::handle_alloc_error(layout)), // oom
60+
)
4961
}
5062
}

0 commit comments

Comments
 (0)