Skip to content

Commit e7eb7d5

Browse files
committed
Auto merge of #27723 - mystor:vecdeque_drain_range, r=bluss
This is a WIP PR for my implementation of drain over the VecDeque data structure supporting ranges. It brings the VecDeque drain implementation in line with Vec's. Tests haven't been written for the new function yet.
2 parents a9d5285 + dec0ea0 commit e7eb7d5

File tree

3 files changed

+280
-19
lines changed

3 files changed

+280
-19
lines changed

src/libcollections/vec_deque.rs

+274-14
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ use core::cmp;
3232

3333
use alloc::raw_vec::RawVec;
3434

35+
use super::range::RangeArgument;
36+
3537
const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
3638
const MINIMUM_CAPACITY: usize = 1; // 2 - 1
3739
const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible power of two
@@ -168,6 +170,117 @@ impl<T> VecDeque<T> {
168170
len);
169171
}
170172

173+
/// Copies a potentially wrapping block of memory len long from src to dest.
174+
/// (abs(dst - src) + len) must be no larger than cap() (There must be at
175+
/// most one continuous overlapping region between src and dest).
176+
unsafe fn wrap_copy(&self, dst: usize, src: usize, len: usize) {
177+
debug_assert!(
178+
(if src <= dst { dst - src } else { src - dst }) + len <= self.cap(),
179+
"dst={} src={} len={} cap={}", dst, src, len, self.cap());
180+
181+
if src == dst || len == 0 { return }
182+
183+
let dst_after_src = self.wrap_sub(dst, src) < len;
184+
185+
let src_pre_wrap_len = self.cap() - src;
186+
let dst_pre_wrap_len = self.cap() - dst;
187+
let src_wraps = src_pre_wrap_len < len;
188+
let dst_wraps = dst_pre_wrap_len < len;
189+
190+
match (dst_after_src, src_wraps, dst_wraps) {
191+
(_, false, false) => {
192+
// src doesn't wrap, dst doesn't wrap
193+
//
194+
// S . . .
195+
// 1 [_ _ A A B B C C _]
196+
// 2 [_ _ A A A A B B _]
197+
// D . . .
198+
//
199+
self.copy(dst, src, len);
200+
}
201+
(false, false, true) => {
202+
// dst before src, src doesn't wrap, dst wraps
203+
//
204+
// S . . .
205+
// 1 [A A B B _ _ _ C C]
206+
// 2 [A A B B _ _ _ A A]
207+
// 3 [B B B B _ _ _ A A]
208+
// . . D .
209+
//
210+
self.copy(dst, src, dst_pre_wrap_len);
211+
self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len);
212+
}
213+
(true, false, true) => {
214+
// src before dst, src doesn't wrap, dst wraps
215+
//
216+
// S . . .
217+
// 1 [C C _ _ _ A A B B]
218+
// 2 [B B _ _ _ A A B B]
219+
// 3 [B B _ _ _ A A A A]
220+
// . . D .
221+
//
222+
self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len);
223+
self.copy(dst, src, dst_pre_wrap_len);
224+
}
225+
(false, true, false) => {
226+
// dst before src, src wraps, dst doesn't wrap
227+
//
228+
// . . S .
229+
// 1 [C C _ _ _ A A B B]
230+
// 2 [C C _ _ _ B B B B]
231+
// 3 [C C _ _ _ B B C C]
232+
// D . . .
233+
//
234+
self.copy(dst, src, src_pre_wrap_len);
235+
self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len);
236+
}
237+
(true, true, false) => {
238+
// src before dst, src wraps, dst doesn't wrap
239+
//
240+
// . . S .
241+
// 1 [A A B B _ _ _ C C]
242+
// 2 [A A A A _ _ _ C C]
243+
// 3 [C C A A _ _ _ C C]
244+
// D . . .
245+
//
246+
self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len);
247+
self.copy(dst, src, src_pre_wrap_len);
248+
}
249+
(false, true, true) => {
250+
// dst before src, src wraps, dst wraps
251+
//
252+
// . . . S .
253+
// 1 [A B C D _ E F G H]
254+
// 2 [A B C D _ E G H H]
255+
// 3 [A B C D _ E G H A]
256+
// 4 [B C C D _ E G H A]
257+
// . . D . .
258+
//
259+
debug_assert!(dst_pre_wrap_len > src_pre_wrap_len);
260+
let delta = dst_pre_wrap_len - src_pre_wrap_len;
261+
self.copy(dst, src, src_pre_wrap_len);
262+
self.copy(dst + src_pre_wrap_len, 0, delta);
263+
self.copy(0, delta, len - dst_pre_wrap_len);
264+
}
265+
(true, true, true) => {
266+
// src before dst, src wraps, dst wraps
267+
//
268+
// . . S . .
269+
// 1 [A B C D _ E F G H]
270+
// 2 [A A B D _ E F G H]
271+
// 3 [H A B D _ E F G H]
272+
// 4 [H A B D _ E F F G]
273+
// . . . D .
274+
//
275+
debug_assert!(src_pre_wrap_len > dst_pre_wrap_len);
276+
let delta = src_pre_wrap_len - dst_pre_wrap_len;
277+
self.copy(delta, 0, len - src_pre_wrap_len);
278+
self.copy(0, self.cap() - delta, delta);
279+
self.copy(dst, src, dst_pre_wrap_len);
280+
}
281+
}
282+
}
283+
171284
/// Frobs the head and tail sections around to handle the fact that we
172285
/// just reallocated. Unsafe because it trusts old_cap.
173286
#[inline]
@@ -613,8 +726,18 @@ impl<T> VecDeque<T> {
613726
#[stable(feature = "rust1", since = "1.0.0")]
614727
pub fn is_empty(&self) -> bool { self.len() == 0 }
615728

616-
/// Creates a draining iterator that clears the `VecDeque` and iterates over
617-
/// the removed items from start to end.
729+
/// Create a draining iterator that removes the specified range in the
730+
/// `VecDeque` and yields the removed items from start to end. The element
731+
/// range is removed even if the iterator is not consumed until the end.
732+
///
733+
/// Note: It is unspecified how many elements are removed from the deque,
734+
/// if the `Drain` value is not dropped, but the borrow it holds expires
735+
/// (eg. due to mem::forget).
736+
///
737+
/// # Panics
738+
///
739+
/// Panics if the starting point is greater than the end point or if
740+
/// the end point is greater than the length of the vector.
618741
///
619742
/// # Examples
620743
///
@@ -623,18 +746,66 @@ impl<T> VecDeque<T> {
623746
///
624747
/// use std::collections::VecDeque;
625748
///
749+
/// // draining using `..` clears the whole deque.
626750
/// let mut v = VecDeque::new();
627751
/// v.push_back(1);
628-
/// assert_eq!(v.drain().next(), Some(1));
752+
/// assert_eq!(v.drain(..).next(), Some(1));
629753
/// assert!(v.is_empty());
630754
/// ```
631755
#[inline]
632756
#[unstable(feature = "drain",
633757
reason = "matches collection reform specification, waiting for dust to settle",
634758
issue = "27711")]
635-
pub fn drain(&mut self) -> Drain<T> {
759+
pub fn drain<R>(&mut self, range: R) -> Drain<T> where R: RangeArgument<usize> {
760+
// Memory safety
761+
//
762+
// When the Drain is first created, the source deque is shortened to
763+
// make sure no uninitialized or moved-from elements are accessible at
764+
// all if the Drain's destructor never gets to run.
765+
//
766+
// Drain will ptr::read out the values to remove.
767+
// When finished, the remaining data will be copied back to cover the hole,
768+
// and the head/tail values will be restored correctly.
769+
//
770+
let len = self.len();
771+
let start = *range.start().unwrap_or(&0);
772+
let end = *range.end().unwrap_or(&len);
773+
assert!(start <= end, "drain lower bound was too large");
774+
assert!(end <= len, "drain upper bound was too large");
775+
776+
// The deque's elements are parted into three segments:
777+
// * self.tail -> drain_tail
778+
// * drain_tail -> drain_head
779+
// * drain_head -> self.head
780+
//
781+
// T = self.tail; H = self.head; t = drain_tail; h = drain_head
782+
//
783+
// We store drain_tail as self.head, and drain_head and self.head as
784+
// after_tail and after_head respectively on the Drain. This also
785+
// truncates the effective array such that if the Drain is leaked, we
786+
// have forgotten about the potentially moved values after the start of
787+
// the drain.
788+
//
789+
// T t h H
790+
// [. . . o o x x o o . . .]
791+
//
792+
let drain_tail = self.wrap_add(self.tail, start);
793+
let drain_head = self.wrap_add(self.tail, end);
794+
let head = self.head;
795+
796+
// "forget" about the values after the start of the drain until after
797+
// the drain is complete and the Drain destructor is run.
798+
self.head = drain_tail;
799+
636800
Drain {
637-
inner: self,
801+
deque: self as *mut _,
802+
after_tail: drain_head,
803+
after_head: head,
804+
iter: Iter {
805+
tail: drain_tail,
806+
head: drain_head,
807+
ring: unsafe { self.buffer_as_mut_slice() },
808+
},
638809
}
639810
}
640811

@@ -653,7 +824,7 @@ impl<T> VecDeque<T> {
653824
#[stable(feature = "rust1", since = "1.0.0")]
654825
#[inline]
655826
pub fn clear(&mut self) {
656-
self.drain();
827+
self.drain(..);
657828
}
658829

659830
/// Provides a reference to the front element, or `None` if the sequence is
@@ -1393,7 +1564,7 @@ impl<T> VecDeque<T> {
13931564
#[stable(feature = "append", since = "1.4.0")]
13941565
pub fn append(&mut self, other: &mut Self) {
13951566
// naive impl
1396-
self.extend(other.drain());
1567+
self.extend(other.drain(..));
13971568
}
13981569

13991570
/// Retains only the elements specified by the predicate.
@@ -1627,15 +1798,59 @@ impl<T> ExactSizeIterator for IntoIter<T> {}
16271798
reason = "matches collection reform specification, waiting for dust to settle",
16281799
issue = "27711")]
16291800
pub struct Drain<'a, T: 'a> {
1630-
inner: &'a mut VecDeque<T>,
1801+
after_tail: usize,
1802+
after_head: usize,
1803+
iter: Iter<'a, T>,
1804+
deque: *mut VecDeque<T>,
16311805
}
16321806

1807+
unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
1808+
unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
1809+
16331810
#[stable(feature = "rust1", since = "1.0.0")]
16341811
impl<'a, T: 'a> Drop for Drain<'a, T> {
16351812
fn drop(&mut self) {
16361813
for _ in self.by_ref() {}
1637-
self.inner.head = 0;
1638-
self.inner.tail = 0;
1814+
1815+
let source_deque = unsafe { &mut *self.deque };
1816+
1817+
// T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head
1818+
//
1819+
// T t h H
1820+
// [. . . o o x x o o . . .]
1821+
//
1822+
let orig_tail = source_deque.tail;
1823+
let drain_tail = source_deque.head;
1824+
let drain_head = self.after_tail;
1825+
let orig_head = self.after_head;
1826+
1827+
let tail_len = count(orig_tail, drain_tail, source_deque.cap());
1828+
let head_len = count(drain_head, orig_head, source_deque.cap());
1829+
1830+
// Restore the original head value
1831+
source_deque.head = orig_head;
1832+
1833+
match (tail_len, head_len) {
1834+
(0, 0) => {
1835+
source_deque.head = 0;
1836+
source_deque.tail = 0;
1837+
}
1838+
(0, _) => {
1839+
source_deque.tail = drain_head;
1840+
}
1841+
(_, 0) => {
1842+
source_deque.head = drain_tail;
1843+
}
1844+
_ => unsafe {
1845+
if tail_len <= head_len {
1846+
source_deque.tail = source_deque.wrap_sub(drain_head, tail_len);
1847+
source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len);
1848+
} else {
1849+
source_deque.head = source_deque.wrap_add(drain_tail, head_len);
1850+
source_deque.wrap_copy(drain_tail, drain_head, head_len);
1851+
}
1852+
}
1853+
}
16391854
}
16401855
}
16411856

@@ -1645,21 +1860,28 @@ impl<'a, T: 'a> Iterator for Drain<'a, T> {
16451860

16461861
#[inline]
16471862
fn next(&mut self) -> Option<T> {
1648-
self.inner.pop_front()
1863+
self.iter.next().map(|elt|
1864+
unsafe {
1865+
ptr::read(elt)
1866+
}
1867+
)
16491868
}
16501869

16511870
#[inline]
16521871
fn size_hint(&self) -> (usize, Option<usize>) {
1653-
let len = self.inner.len();
1654-
(len, Some(len))
1872+
self.iter.size_hint()
16551873
}
16561874
}
16571875

16581876
#[stable(feature = "rust1", since = "1.0.0")]
16591877
impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
16601878
#[inline]
16611879
fn next_back(&mut self) -> Option<T> {
1662-
self.inner.pop_back()
1880+
self.iter.next_back().map(|elt|
1881+
unsafe {
1882+
ptr::read(elt)
1883+
}
1884+
)
16631885
}
16641886
}
16651887

@@ -1962,6 +2184,44 @@ mod tests {
19622184
}
19632185
}
19642186

2187+
#[test]
2188+
fn test_drain() {
2189+
let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);
2190+
2191+
let cap = tester.capacity();
2192+
for len in 0..cap + 1 {
2193+
for tail in 0..cap + 1 {
2194+
for drain_start in 0..len + 1 {
2195+
for drain_end in drain_start..len + 1 {
2196+
tester.tail = tail;
2197+
tester.head = tail;
2198+
for i in 0..len {
2199+
tester.push_back(i);
2200+
}
2201+
2202+
// Check that we drain the correct values
2203+
let drained: VecDeque<_> =
2204+
tester.drain(drain_start..drain_end).collect();
2205+
let drained_expected: VecDeque<_> =
2206+
(drain_start..drain_end).collect();
2207+
assert_eq!(drained, drained_expected);
2208+
2209+
// We shouldn't have changed the capacity or made the
2210+
// head or tail out of bounds
2211+
assert_eq!(tester.capacity(), cap);
2212+
assert!(tester.tail < tester.cap());
2213+
assert!(tester.head < tester.cap());
2214+
2215+
// We should see the correct values in the VecDeque
2216+
let expected: VecDeque<_> =
2217+
(0..drain_start).chain(drain_end..len).collect();
2218+
assert_eq!(expected, tester);
2219+
}
2220+
}
2221+
}
2222+
}
2223+
}
2224+
19652225
#[test]
19662226
fn test_shrink_to_fit() {
19672227
// This test checks that every single combination of head and tail position,

0 commit comments

Comments
 (0)