@@ -2152,37 +2152,77 @@ impl<T, A: Allocator> VecDeque<T, A> {
2152
2152
2153
2153
self . head = tail;
2154
2154
} else {
2155
- // free is smaller than both head and tail,
2156
- // this means we have to slowly "swap" the tail and the head.
2155
+ // ´free` is smaller than both `head_len` and `tail_len`.
2156
+ // the general algorithm for this first moves the slices
2157
+ // right next to each other and then uses `slice::rotate`
2158
+ // to rotate them into place:
2157
2159
//
2158
- // from: EFGHI...ABCD or HIJK.ABCDEFG
2159
- // to: ABCDEFGHI... or ABCDEFGHIJK.
2160
- let mut left_edge: usize = 0 ;
2161
- let mut right_edge: usize = head;
2162
- unsafe {
2163
- // The general problem looks like this
2164
- // GHIJKLM...ABCDEF - before any swaps
2165
- // ABCDEFM...GHIJKL - after 1 pass of swaps
2166
- // ABCDEFGHIJM...KL - swap until the left edge reaches the temp store
2167
- // - then restart the algorithm with a new (smaller) store
2168
- // Sometimes the temp store is reached when the right edge is at the end
2169
- // of the buffer - this means we've hit the right order with fewer swaps!
2170
- // E.g
2171
- // EF..ABCD
2172
- // ABCDEF.. - after four only swaps we've finished
2173
- while left_edge < len && right_edge != cap {
2174
- let mut right_offset = 0 ;
2175
- for i in left_edge..right_edge {
2176
- right_offset = ( i - left_edge) % ( cap - right_edge) ;
2177
- let src = right_edge + right_offset;
2178
- ptr:: swap ( ptr. add ( i) , ptr. add ( src) ) ;
2160
+ // initially: HIJK..ABCDEFG
2161
+ // step 1: ..HIJKABCDEFG
2162
+ // step 2: ..ABCDEFGHIJK
2163
+ //
2164
+ // or:
2165
+ //
2166
+ // initially: FGHIJK..ABCDE
2167
+ // step 1: FGHIJKABCDE..
2168
+ // step 2: ABCDEFGHIJK..
2169
+
2170
+ // pick the shorter of the 2 slices to reduce the amount
2171
+ // of memory that needs to be moved around.
2172
+ if head_len > tail_len {
2173
+ // tail is shorter, so:
2174
+ // 1. copy tail forwards
2175
+ // 2. rotate used part of the buffer
2176
+ // 3. update head to point to the new beginning (which is just `free`)
2177
+
2178
+ unsafe {
2179
+ // if there is no free space in the buffer, then the slices are already
2180
+ // right next to each other and we don't need to move any memory.
2181
+ if free != 0 {
2182
+ // because we only move the tail forward as much as there's free space
2183
+ // behind it, we don't overwrite any elements of the head slice, and
2184
+ // the slices end up right next to each other.
2185
+ self . copy ( 0 , free, tail_len) ;
2179
2186
}
2180
- let n_ops = right_edge - left_edge;
2181
- left_edge += n_ops;
2182
- right_edge += right_offset + 1 ;
2187
+
2188
+ // We just copied the tail right next to the head slice,
2189
+ // so all of the elements in the range are initialized
2190
+ let slice = & mut * self . buffer_range ( free..self . capacity ( ) ) ;
2191
+
2192
+ // because the deque wasn't contiguous, we know that `tail_len < self.len == slice.len()`,
2193
+ // so this will never panic.
2194
+ slice. rotate_left ( tail_len) ;
2195
+
2196
+ // the used part of the buffer now is `free..self.capacity()`, so set
2197
+ // `head` to the beginning of that range.
2198
+ self . head = free;
2183
2199
}
2200
+ } else {
2201
+ // head is shorter so:
2202
+ // 1. copy head backwards
2203
+ // 2. rotate used part of the buffer
2204
+ // 3. update head to point to the new beginning (which is the beginning of the buffer)
2184
2205
2185
- self . head = 0 ;
2206
+ unsafe {
2207
+ // if there is no free space in the buffer, then the slices are already
2208
+ // right next to each other and we don't need to move any memory.
2209
+ if free != 0 {
2210
+ // copy the head slice to lie right behind the tail slice.
2211
+ self . copy ( self . head , tail_len, head_len) ;
2212
+ }
2213
+
2214
+ // because we copied the head slice so that both slices lie right
2215
+ // next to each other, all the elements in the range are initialized.
2216
+ let slice = & mut * self . buffer_range ( 0 ..self . len ) ;
2217
+
2218
+ // because the deque wasn't contiguous, we know that `head_len < self.len == slice.len()`
2219
+ // so this will never panic.
2220
+ slice. rotate_right ( head_len) ;
2221
+
2222
+ // the used part of the buffer now is `0..self.len`, so set
2223
+ // `head` to the beginning of that range.
2224
+ self . head = 0 ;
2225
+ }
2186
2226
}
2187
2227
}
2188
2228
0 commit comments