diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2013-05-06 00:43:06 -0400 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2013-05-10 22:51:06 -0400 |
| commit | 7d22437ecdc5b52f8517ffde6207347739b26553 (patch) | |
| tree | 2f197874c35d9fce98538d2e7b89b2070e7f56e9 /src | |
| parent | 3e0400fb86170baff30282edcdccff73e243fd6e (diff) | |
| download | rust-7d22437ecdc5b52f8517ffde6207347739b26553.tar.gz rust-7d22437ecdc5b52f8517ffde6207347739b26553.zip | |
Implement util::swap without the '<->' operator
Diffstat (limited to 'src')
| -rw-r--r-- | src/libcore/util.rs | 68 |
1 files changed, 63 insertions, 5 deletions
diff --git a/src/libcore/util.rs b/src/libcore/util.rs index 43616ebfd30..c6b82b9aeec 100644 --- a/src/libcore/util.rs +++ b/src/libcore/util.rs @@ -15,6 +15,7 @@ Miscellaneous helpers for common patterns. */ use prelude::*; +use unstable::intrinsics; /// The identity function. #[inline(always)] @@ -49,7 +50,65 @@ pub fn with<T,R>( */ #[inline(always)] pub fn swap<T>(x: &mut T, y: &mut T) { - *x <-> *y; + unsafe { + swap_ptr(ptr::to_mut_unsafe_ptr(x), ptr::to_mut_unsafe_ptr(y)); + } +} + +/** + * Swap the values at two mutable locations of the same type, without + * deinitialising or copying either one. + */ +#[inline] +#[cfg(not(stage0))] +pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) { + if x == y { return } + + // Give ourselves some scratch space to work with + let mut tmp: T = intrinsics::uninit(); + let t = ptr::to_mut_unsafe_ptr(&mut tmp); + + // Perform the swap + ptr::copy_memory(t, x, 1); + ptr::copy_memory(x, y, 1); + ptr::copy_memory(y, t, 1); + + // y and t now point to the same thing, but we need to completely forget t + // because it's no longer relevant. + cast::forget(tmp); +} + +/** + * Swap the values at two mutable locations of the same type, without + * deinitialising or copying either one. + */ +#[inline] +#[cfg(stage0)] +pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) { + if x == y { return } + + // Give ourselves some scratch space to work with + let mut tmp: T = intrinsics::init(); + let t = ptr::to_mut_unsafe_ptr(&mut tmp); + + // Perform the swap + ptr::copy_memory(t, x, 1); + ptr::copy_memory(x, y, 1); + ptr::copy_memory(y, t, 1); + + // y and t now point to the same thing, but we need to completely forget t + // because it's no longer relevant. + cast::forget(tmp); +} + +/** + * Replace the value at a mutable location with a new one, returning the old + * value, without deinitialising or copying either one. + */ +#[inline(always)] +pub fn replace<T>(dest: &mut T, mut src: T) -> T { + swap(dest, &mut src); + src } /** @@ -57,10 +116,9 @@ pub fn swap<T>(x: &mut T, y: &mut T) { * value, without deinitialising or copying either one. */ #[inline(always)] -pub fn replace<T>(dest: &mut T, src: T) -> T { - let mut tmp = src; - swap(dest, &mut tmp); - tmp +pub unsafe fn replace_ptr<T>(dest: *mut T, mut src: T) -> T { + swap_ptr(dest, ptr::to_mut_unsafe_ptr(&mut src)); + src } /// A non-copyable dummy type. |
