1
Fork 0

speed up mem::swap

This commit is contained in:
Djzin 2017-03-12 13:14:47 +00:00
parent f84a517483
commit 4bcfbc36c6

View file

@ -109,7 +109,7 @@ pub use intrinsics::transmute;
/// [`Clone`][clone]. You need the value's destructor to run only once, /// [`Clone`][clone]. You need the value's destructor to run only once,
/// because a double `free` is undefined behavior. /// because a double `free` is undefined behavior.
/// ///
/// An example is the definition of [`mem::swap`][swap] in this module: /// An example is the (old) definition of [`mem::swap`][swap] in this module:
/// ///
/// ``` /// ```
/// use std::mem; /// use std::mem;
@ -447,18 +447,15 @@ pub unsafe fn uninitialized<T>() -> T {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn swap<T>(x: &mut T, y: &mut T) { pub fn swap<T>(x: &mut T, y: &mut T) {
unsafe { unsafe {
// Give ourselves some scratch space to work with let x = x as *mut T as *mut u8;
let mut t: T = uninitialized(); let y = y as *mut T as *mut u8;
// Perform the swap, `&mut` pointers never alias // use an xor-swap as x & y are guaranteed to never alias
ptr::copy_nonoverlapping(&*x, &mut t, 1); for i in 0..size_of::<T>() as isize {
ptr::copy_nonoverlapping(&*y, x, 1); *x.offset(i) ^= *y.offset(i);
ptr::copy_nonoverlapping(&t, y, 1); *y.offset(i) ^= *x.offset(i);
*x.offset(i) ^= *y.offset(i);
// y and t now point to the same thing, but we need to completely }
// forget `t` because we do not want to run the destructor for `T`
// on its value, which is still owned somewhere outside this function.
forget(t);
} }
} }