/// A double-ended queue implemented with a growable ring buffer. /// /// The "default" usage of this type as a queue is to use [`push_back`] to add to /// the queue, and [`pop_front`] to remove from the queue. [`extend`] and [`append`] /// push onto the back in this manner, and iterating over `VecDeque` goes front /// to back. /// /// [`push_back`]: #method.push_back /// [`pop_front`]: #method.pop_front /// [`extend`]: #method.extend /// [`append`]: #method.append #[stable(feature = "rust1", since = "1.0.0")] pub structVecDeque<T> { // tail and head are pointers into the buffer. Tail always points // to the first element that could be read, Head always points // to where data should be written. // If tail == head the buffer is empty. The length of the ringbuffer // is defined as the distance between the two. tail: usize, head: usize, buf: RawVec<T>, }
wrap 其实想一想很清晰,这个不是直接去取地址,而是在 ring buffer 里面拿到一个相对的地址。
1 2 3 4 5 6 7
/// Returns the index in the underlying buffer for a given logical element /// index + addend. #[inline] fnwrap_add(&self, idx: usize, addend: usize) ->usize { wrap_index(idx.wrapping_add(addend), self.cap()) }
wrap_index:
1 2 3 4 5 6 7
/// Returns the index in the underlying buffer for a given logical element index. #[inline] fnwrap_index(index: usize, size: usize) ->usize { // size is always a power of 2 debug_assert!(size.is_power_of_two()); index & (size - 1) }
这个 size 其实是 RawVec 的 cap. 我们之前看到了 cap 会保证自己是 2 的倍数, 这里也有 debug_assert。所以 index & (size - 1) 相当于 index % size. 拿到这里对应的 index。迭代器、index 都是用这一套的。
// since we set the capacity to usize::MAX when elem_size is // 0, getting to here necessarily means the RawVec is overfull. assert!(elem_size != 0, "capacity overflow");
let (new_cap, uniq) = matchself.current_layout() { Some(cur) => { // Since we guarantee that we never allocate more than // isize::MAX bytes, `elem_size * self.cap <= isize::MAX` as // a precondition, so this can't overflow. Additionally the // alignment will never be too large as to "not be // satisfiable", so `Layout::from_size_align` will always // return `Some`. // // tl;dr; we bypass runtime checks due to dynamic assertions // in this module, allowing us to use // `from_size_align_unchecked`. letnew_cap = 2 * self.cap; letnew_size = new_cap * elem_size; alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow()); letptr_res = self.a.realloc(NonNull::from(self.ptr).cast(), cur, new_size); match ptr_res { Ok(ptr) => (new_cap, ptr.cast().into()), Err(_) => handle_alloc_error( Layout::from_size_align_unchecked(new_size, cur.align()) ), } } None => { // skip to 4 because tiny Vec's are dumb; but not if that // would cause overflow letnew_cap = if elem_size > (!0) / 8 { 1 } else { 4 }; matchself.a.alloc_array::<T>(new_cap) { Ok(ptr) => (new_cap, ptr.into()), Err(_) => handle_alloc_error(Layout::array::<T>(new_cap).unwrap()), } } }; self.ptr = uniq; self.cap = new_cap; } }
/// Frobs the head and tail sections around to handle the fact that we /// just reallocated. Unsafe because it trusts old_capacity. #[inline] unsafefnhandle_capacity_increase(&mutself, old_capacity: usize) { letnew_capacity = self.cap();
// Move the shortest contiguous section of the ring buffer // T H // [o o o o o o o . ] // T H // A [o o o o o o o . . . . . . . . . ] // H T // [o o . o o o o o ] // T H // B [. . . o o o o o o o . . . . . . ] // H T // [o o o o o . o o ] // H T // C [o o o o o . . . . . . . . . o o ]
/// Returns the two slices that cover the `VecDeque`'s valid range traitRingSlices: Sized { fnslice(self, from: usize, to: usize) ->Self; fnsplit_at(self, i: usize) -> (Self, Self);