@@ -2152,37 +2152,77 @@ impl<T, A: Allocator> VecDeque<T, A> {
21522152
21532153 self . head = tail;
21542154 } 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:
21572159 //
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) ;
21792186 }
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;
21832199 }
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)
21842205
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+ }
21862226 }
21872227 }
21882228
0 commit comments