Auto merge of #38309 - sfackler:rfc-1725, r=alexcrichton
Implement RFC #1725 (read_unaligned, write_unaligned) cc #37955 r? @alexcrichton
This commit is contained in:
commit
0d1b9f4614
@ -117,6 +117,8 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
|
||||
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
|
||||
/// because it will attempt to drop the value previously at `*src`.
|
||||
///
|
||||
/// The pointer must be aligned; use `read_unaligned` if that is not the case.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
@ -137,6 +139,44 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
||||
tmp
|
||||
}
|
||||
|
||||
/// Reads the value from `src` without moving it. This leaves the
|
||||
/// memory in `src` unchanged.
|
||||
///
|
||||
/// Unlike `read`, the pointer may be unaligned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Beyond accepting a raw pointer, this is unsafe because it semantically
|
||||
/// moves the value out of `src` without preventing further usage of `src`.
|
||||
/// If `T` is not `Copy`, then care must be taken to ensure that the value at
|
||||
/// `src` is not used before the data is overwritten again (e.g. with `write`,
|
||||
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
|
||||
/// because it will attempt to drop the value previously at `*src`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_unaligned)]
|
||||
///
|
||||
/// let x = 12;
|
||||
/// let y = &x as *const i32;
|
||||
///
|
||||
/// unsafe {
|
||||
/// assert_eq!(std::ptr::read_unaligned(y), 12);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[unstable(feature = "ptr_unaligned", issue = "37955")]
|
||||
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
|
||||
let mut tmp: T = mem::uninitialized();
|
||||
copy_nonoverlapping(src as *const u8,
|
||||
&mut tmp as *mut T as *mut u8,
|
||||
mem::size_of::<T>());
|
||||
tmp
|
||||
}
|
||||
|
||||
/// Overwrites a memory location with the given value without reading or
|
||||
/// dropping the old value.
|
||||
///
|
||||
@ -151,6 +191,8 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
||||
/// This is appropriate for initializing uninitialized memory, or overwriting
|
||||
/// memory that has previously been `read` from.
|
||||
///
|
||||
/// The pointer must be aligned; use `write_unaligned` if that is not the case.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
@ -171,6 +213,47 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
|
||||
intrinsics::move_val_init(&mut *dst, src)
|
||||
}
|
||||
|
||||
/// Overwrites a memory location with the given value without reading or
|
||||
/// dropping the old value.
|
||||
///
|
||||
/// Unlike `write`, the pointer may be unaligned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This operation is marked unsafe because it accepts a raw pointer.
|
||||
///
|
||||
/// It does not drop the contents of `dst`. This is safe, but it could leak
|
||||
/// allocations or resources, so care must be taken not to overwrite an object
|
||||
/// that should be dropped.
|
||||
///
|
||||
/// This is appropriate for initializing uninitialized memory, or overwriting
|
||||
/// memory that has previously been `read` from.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_unaligned)]
|
||||
///
|
||||
/// let mut x = 0;
|
||||
/// let y = &mut x as *mut i32;
|
||||
/// let z = 12;
|
||||
///
|
||||
/// unsafe {
|
||||
/// std::ptr::write_unaligned(y, z);
|
||||
/// assert_eq!(std::ptr::read_unaligned(y), 12);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "ptr_unaligned", issue = "37955")]
|
||||
pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
|
||||
copy_nonoverlapping(&src as *const T as *const u8,
|
||||
dst as *mut u8,
|
||||
mem::size_of::<T>());
|
||||
mem::forget(src);
|
||||
}
|
||||
|
||||
/// Performs a volatile read of the value from `src` without moving it. This
|
||||
/// leaves the memory in `src` unchanged.
|
||||
///
|
||||
|
@ -36,6 +36,7 @@
|
||||
#![feature(iter_min_by)]
|
||||
#![feature(ordering_chaining)]
|
||||
#![feature(result_unwrap_or_default)]
|
||||
#![feature(ptr_unaligned)]
|
||||
|
||||
extern crate core;
|
||||
extern crate test;
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use core::ptr::*;
|
||||
use core::cell::RefCell;
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
@ -189,3 +190,25 @@ pub fn test_variadic_fnptr() {
|
||||
let mut s = SipHasher::new();
|
||||
assert_eq!(p.hash(&mut s), q.hash(&mut s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_unaligned_drop() {
|
||||
thread_local! {
|
||||
static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
|
||||
}
|
||||
|
||||
struct Dropper(u32);
|
||||
|
||||
impl Drop for Dropper {
|
||||
fn drop(&mut self) {
|
||||
DROPS.with(|d| d.borrow_mut().push(self.0));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let c = Dropper(0);
|
||||
let mut t = Dropper(1);
|
||||
unsafe { write_unaligned(&mut t, c); }
|
||||
}
|
||||
DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user