auto merge of #14529 : brson/rust/ptr, r=brson

This time we're not promoting anything directly to 'stable', but instead promoting functions we're happy with to 'unstable'. They'll become stable in another pass later.

* null and mut_null are unstable. Their names may change if the unsafe
  pointer types change.
* copy_memory and copy_overlapping_memory are unstable. We think they
  aren't going to change.
* set_memory and zero_memory are experimental. Both the names and
  the semantics are under question.
* swap and replace are unstable and probably won't change.
* read is unstable, probably won't change
* read_and_zero is experimental. It's necessity is in doubt.
* mem::overwrite is now called ptr::write to match read and is
  unstable. mem::overwrite is now deprecated
* array_each, array_each_with_len, buf_len, and position are
  all deprecated because they use old style iteration and their
  utility is generally under question.

Note that `mem::overwrite`, which was just declared stable last week, is deprecated now in favor of `ptr::write`. Woo!
This commit is contained in:
bors 2014-06-04 18:56:48 -07:00
commit 193574ae1e
7 changed files with 80 additions and 48 deletions

View File

@ -213,14 +213,14 @@ pub struct Unique<T> {
impl<T: Send> Unique<T> {
pub fn new(value: T) -> Unique<T> {
unsafe {
let ptr = malloc(std::mem::size_of::<T>() as size_t) as *mut T;
let ptr = malloc(mem::size_of::<T>() as size_t) as *mut T;
// we *need* valid pointer.
assert!(!ptr.is_null());
// `*ptr` is uninitialized, and `*ptr = value` would
// attempt to destroy it `overwrite` moves a value into
// this memory without attempting to drop the original
// value.
mem::overwrite(&mut *ptr, value);
ptr::write(&mut *ptr, value);
Unique{ptr: ptr}
}
}

View File

@ -36,7 +36,7 @@ use std::intrinsics::{TyDesc, get_tydesc};
use std::intrinsics;
use std::mem;
use std::num;
use std::ptr::read;
use std::ptr;
use std::rc::Rc;
use std::rt::heap::allocate;
@ -209,7 +209,7 @@ impl Arena {
let ptr = self.alloc_copy_inner(mem::size_of::<T>(),
mem::min_align_of::<T>());
let ptr = ptr as *mut T;
mem::overwrite(&mut (*ptr), op());
ptr::write(&mut (*ptr), op());
return &*ptr;
}
}
@ -262,7 +262,7 @@ impl Arena {
// has *not* been initialized yet.
*ty_ptr = mem::transmute(tydesc);
// Actually initialize it
mem::overwrite(&mut(*ptr), op());
ptr::write(&mut(*ptr), op());
// Now that we are done, update the tydesc to indicate that
// the object is there.
*ty_ptr = bitpack_tydesc_ptr(tydesc, true);
@ -360,7 +360,7 @@ impl<T> TypedArenaChunk<T> {
let mut chunk = unsafe {
let chunk = allocate(size, mem::min_align_of::<TypedArenaChunk<T>>());
let mut chunk: Box<TypedArenaChunk<T>> = mem::transmute(chunk);
mem::overwrite(&mut chunk.next, next);
ptr::write(&mut chunk.next, next);
chunk
};
@ -376,7 +376,7 @@ impl<T> TypedArenaChunk<T> {
if intrinsics::needs_drop::<T>() {
let mut start = self.start();
for _ in range(0, len) {
read(start as *T); // run the destructor on the pointer
ptr::read(start as *T); // run the destructor on the pointer
start = start.offset(mem::size_of::<T>() as int)
}
}
@ -442,7 +442,7 @@ impl<T> TypedArena<T> {
}
let ptr: &'a mut T = mem::transmute(this.ptr);
mem::overwrite(ptr, object);
ptr::write(ptr, object);
this.ptr = this.ptr.offset(1);
let ptr: &'a T = ptr;
ptr

View File

@ -13,7 +13,8 @@
#![allow(missing_doc)]
use std::clone::Clone;
use std::mem::{overwrite, zeroed, replace, swap};
use std::mem::{zeroed, replace, swap};
use std::ptr;
use std::slice;
/// A priority queue implemented with a binary heap
@ -163,13 +164,13 @@ impl<T: Ord> PriorityQueue<T> {
let parent = (pos - 1) >> 1;
if new > *self.data.get(parent) {
let x = replace(self.data.get_mut(parent), zeroed());
overwrite(self.data.get_mut(pos), x);
ptr::write(self.data.get_mut(pos), x);
pos = parent;
continue
}
break
}
overwrite(self.data.get_mut(pos), new);
ptr::write(self.data.get_mut(pos), new);
}
}
@ -185,12 +186,12 @@ impl<T: Ord> PriorityQueue<T> {
child = right;
}
let x = replace(self.data.get_mut(child), zeroed());
overwrite(self.data.get_mut(pos), x);
ptr::write(self.data.get_mut(pos), x);
pos = child;
child = 2 * pos + 1;
}
overwrite(self.data.get_mut(pos), new);
ptr::write(self.data.get_mut(pos), new);
self.siftup(start, pos);
}
}

View File

@ -155,16 +155,16 @@ pub unsafe fn uninit<T>() -> T {
/// contained at the location `dst`. This could leak allocations or resources,
/// so care must be taken to previously deallocate the value at `dst`.
#[inline]
#[stable]
#[deprecated = "use ptr::write"]
pub unsafe fn overwrite<T>(dst: *mut T, src: T) {
intrinsics::move_val_init(&mut *dst, src)
}
/// Deprecated, use `overwrite` instead
#[inline]
#[deprecated = "this function has been renamed to `overwrite`"]
#[deprecated = "use ptr::write"]
pub unsafe fn move_val_init<T>(dst: &mut T, src: T) {
overwrite(dst, src)
ptr::write(dst, src)
}
/// Convert an u16 to little endian from the target's endianness.

View File

@ -95,36 +95,6 @@ use option::{Some, None, Option};
#[cfg(not(test))] use cmp::{PartialEq, Eq, PartialOrd, Equiv};
/// Return the offset of the first null pointer in `buf`.
#[inline]
pub unsafe fn buf_len<T>(buf: **T) -> uint {
position(buf, |i| *i == null())
}
impl<T> Clone for *T {
#[inline]
fn clone(&self) -> *T {
*self
}
}
impl<T> Clone for *mut T {
#[inline]
fn clone(&self) -> *mut T {
*self
}
}
/// Return the first offset `i` such that `f(buf[i]) == true`.
#[inline]
pub unsafe fn position<T>(buf: *T, f: |&T| -> bool) -> uint {
let mut i = 0;
loop {
if f(&(*buf.offset(i as int))) { return i; }
else { i += 1; }
}
}
/// Create a null pointer.
///
/// # Example
@ -136,6 +106,7 @@ pub unsafe fn position<T>(buf: *T, f: |&T| -> bool) -> uint {
/// assert!(p.is_null());
/// ```
#[inline]
#[unstable = "may need a different name after pending changes to pointer types"]
pub fn null<T>() -> *T { 0 as *T }
/// Create an unsafe mutable null pointer.
@ -149,6 +120,7 @@ pub fn null<T>() -> *T { 0 as *T }
/// assert!(p.is_null());
/// ```
#[inline]
#[unstable = "may need a different name after pending changes to pointer types"]
pub fn mut_null<T>() -> *mut T { 0 as *mut T }
/// Copies data from one location to another.
@ -174,6 +146,7 @@ pub fn mut_null<T>() -> *mut T { 0 as *mut T }
/// ```
///
#[inline]
#[unstable]
pub unsafe fn copy_memory<T>(dst: *mut T, src: *T, count: uint) {
intrinsics::copy_memory(dst, src, count)
}
@ -215,6 +188,7 @@ pub unsafe fn copy_memory<T>(dst: *mut T, src: *T, count: uint) {
/// If the source and destination overlap then the behavior of this
/// function is undefined.
#[inline]
#[unstable]
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T,
src: *T,
count: uint) {
@ -224,12 +198,15 @@ pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T,
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
/// bytes of memory starting at `dst` to `c`.
#[inline]
#[experimental = "uncertain about naming and semantics"]
pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
intrinsics::set_memory(dst, c, count)
}
/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`
#[inline]
#[experimental = "uncertain about naming and semantics"]
#[allow(experimental)]
pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
set_memory(dst, 0, count);
}
@ -237,6 +214,7 @@ pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
/// Swap the values at two mutable locations of the same type, without
/// deinitialising either. They may overlap.
#[inline]
#[unstable]
pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
// Give ourselves some scratch space to work with
let mut tmp: T = mem::uninitialized();
@ -255,6 +233,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
/// Replace the value at a mutable location with a new one, returning the old
/// value, without deinitialising either.
#[inline]
#[unstable]
pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
mem::swap(mem::transmute(dest), &mut src); // cannot overlap
src
@ -262,6 +241,7 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
/// Reads the value from `*src` and returns it.
#[inline(always)]
#[unstable]
pub unsafe fn read<T>(src: *T) -> T {
let mut tmp: T = mem::uninitialized();
copy_nonoverlapping_memory(&mut tmp, src, 1);
@ -271,6 +251,8 @@ pub unsafe fn read<T>(src: *T) -> T {
/// Reads the value from `*src` and nulls it out.
/// This currently prevents destructors from executing.
#[inline(always)]
#[experimental]
#[allow(experimental)]
pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
// Copy the data out from `dest`:
let tmp = read(&*dest);
@ -281,9 +263,22 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
tmp
}
/// Unsafely overwrite a memory location with the given value without destroying
/// the old value.
///
/// This operation is unsafe because it does not destroy the previous value
/// contained at the location `dst`. This could leak allocations or resources,
/// so care must be taken to previously deallocate the value at `dst`.
#[inline]
#[unstable]
pub unsafe fn write<T>(dst: *mut T, src: T) {
intrinsics::move_val_init(&mut *dst, src)
}
/// Given a **T (pointer to an array of pointers),
/// iterate through each *T, up to the provided `len`,
/// passing to the provided callback function
#[deprecated = "old-style iteration. use a loop and RawPtr::offset"]
pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: |*T|) {
if arr.is_null() {
fail!("ptr::array_each_with_len failure: arr input is null pointer");
@ -303,6 +298,8 @@ pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: |*T|) {
///
/// This will only work with a null-terminated
/// pointer array.
#[deprecated = "old-style iteration. use a loop and RawPtr::offset"]
#[allow(deprecated)]
pub unsafe fn array_each<T>(arr: **T, cb: |*T|) {
if arr.is_null() {
fail!("ptr::array_each_with_len failure: arr input is null pointer");
@ -311,6 +308,25 @@ pub unsafe fn array_each<T>(arr: **T, cb: |*T|) {
array_each_with_len(arr, len, cb);
}
/// Return the offset of the first null pointer in `buf`.
#[inline]
#[deprecated = "use a loop and RawPtr::offset"]
#[allow(deprecated)]
pub unsafe fn buf_len<T>(buf: **T) -> uint {
position(buf, |i| *i == null())
}
/// Return the first offset `i` such that `f(buf[i]) == true`.
#[inline]
#[deprecated = "old-style iteration. use a loop and RawPtr::offset"]
pub unsafe fn position<T>(buf: *T, f: |&T| -> bool) -> uint {
let mut i = 0;
loop {
if f(&(*buf.offset(i as int))) { return i; }
else { i += 1; }
}
}
/// Methods on raw pointers
pub trait RawPtr<T> {
/// Returns the null pointer.
@ -426,6 +442,20 @@ impl<T> Equiv<*T> for *mut T {
}
}
impl<T> Clone for *T {
#[inline]
fn clone(&self) -> *T {
*self
}
}
impl<T> Clone for *mut T {
#[inline]
fn clone(&self) -> *mut T {
*self
}
}
// Equality for extern "C" fn pointers
#[cfg(not(test))]
mod externfnpointers {

View File

@ -77,7 +77,7 @@ impl<A: Clone> Clone for ~[A] {
try_finally(
&mut i, (),
|i, ()| while *i < len {
mem::overwrite(
ptr::write(
&mut(*p.offset(*i as int)),
self.unsafe_ref(*i).clone());
*i += 1;

View File

@ -1093,7 +1093,7 @@ impl<'a,T> MutableVector<'a, T> for &'a mut [T] {
#[inline]
unsafe fn init_elem(self, i: uint, val: T) {
mem::overwrite(&mut (*self.as_mut_ptr().offset(i as int)), val);
ptr::write(&mut (*self.as_mut_ptr().offset(i as int)), val);
}
#[inline]
@ -1218,6 +1218,7 @@ pub mod bytes {
impl<'a> MutableByteVector for &'a mut [u8] {
#[inline]
#[allow(experimental)]
fn set_memory(self, value: u8) {
unsafe { ptr::set_memory(self.as_mut_ptr(), value, self.len()) };
}