Skip to content

Commit 7d22437

Browse files
committed
Implement util::swap without the '<->' operator
1 parent 3e0400f commit 7d22437

File tree

1 file changed

+63
-5
lines changed

1 file changed

+63
-5
lines changed

src/libcore/util.rs

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Miscellaneous helpers for common patterns.
1515
*/
1616

1717
use prelude::*;
18+
use unstable::intrinsics;
1819

1920
/// The identity function.
2021
#[inline(always)]
@@ -49,18 +50,75 @@ pub fn with<T,R>(
4950
*/
5051
#[inline(always)]
5152
pub fn swap<T>(x: &mut T, y: &mut T) {
52-
*x <-> *y;
53+
unsafe {
54+
swap_ptr(ptr::to_mut_unsafe_ptr(x), ptr::to_mut_unsafe_ptr(y));
55+
}
56+
}
57+
58+
/**
59+
* Swap the values at two mutable locations of the same type, without
60+
* deinitialising or copying either one.
61+
*/
62+
#[inline]
63+
#[cfg(not(stage0))]
64+
pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
65+
if x == y { return }
66+
67+
// Give ourselves some scratch space to work with
68+
let mut tmp: T = intrinsics::uninit();
69+
let t = ptr::to_mut_unsafe_ptr(&mut tmp);
70+
71+
// Perform the swap
72+
ptr::copy_memory(t, x, 1);
73+
ptr::copy_memory(x, y, 1);
74+
ptr::copy_memory(y, t, 1);
75+
76+
// y and t now point to the same thing, but we need to completely forget t
77+
// because it's no longer relevant.
78+
cast::forget(tmp);
79+
}
80+
81+
/**
82+
* Swap the values at two mutable locations of the same type, without
83+
* deinitialising or copying either one.
84+
*/
85+
#[inline]
86+
#[cfg(stage0)]
87+
pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
88+
if x == y { return }
89+
90+
// Give ourselves some scratch space to work with
91+
let mut tmp: T = intrinsics::init();
92+
let t = ptr::to_mut_unsafe_ptr(&mut tmp);
93+
94+
// Perform the swap
95+
ptr::copy_memory(t, x, 1);
96+
ptr::copy_memory(x, y, 1);
97+
ptr::copy_memory(y, t, 1);
98+
99+
// y and t now point to the same thing, but we need to completely forget t
100+
// because it's no longer relevant.
101+
cast::forget(tmp);
102+
}
103+
104+
/**
105+
* Replace the value at a mutable location with a new one, returning the old
106+
* value, without deinitialising or copying either one.
107+
*/
108+
#[inline(always)]
109+
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
110+
swap(dest, &mut src);
111+
src
53112
}
54113

55114
/**
56115
* Replace the value at a mutable location with a new one, returning the old
57116
* value, without deinitialising or copying either one.
58117
*/
59118
#[inline(always)]
60-
pub fn replace<T>(dest: &mut T, src: T) -> T {
61-
let mut tmp = src;
62-
swap(dest, &mut tmp);
63-
tmp
119+
pub unsafe fn replace_ptr<T>(dest: *mut T, mut src: T) -> T {
120+
swap_ptr(dest, ptr::to_mut_unsafe_ptr(&mut src));
121+
src
64122
}
65123

66124
/// A non-copyable dummy type.

0 commit comments

Comments
 (0)