1
- use core:: fmt;
2
1
use core:: iter:: FusedIterator ;
3
2
use core:: marker:: PhantomData ;
4
- use core:: mem:: { self , MaybeUninit } ;
5
- use core:: ptr:: { self , NonNull } ;
3
+ use core:: mem:: { self , SizedTypeProperties } ;
4
+ use core:: ptr:: NonNull ;
5
+ use core:: { fmt, ptr} ;
6
6
7
7
use crate :: alloc:: { Allocator , Global } ;
8
8
9
- use super :: { count , wrap_index , VecDeque } ;
9
+ use super :: VecDeque ;
10
10
11
11
/// A draining iterator over the elements of a `VecDeque`.
12
12
///
@@ -20,38 +20,72 @@ pub struct Drain<
20
20
T : ' a ,
21
21
#[ unstable( feature = "allocator_api" , issue = "32838" ) ] A : Allocator = Global ,
22
22
> {
23
- after_tail : usize ,
24
- after_head : usize ,
25
- ring : NonNull < [ T ] > ,
26
- tail : usize ,
27
- head : usize ,
23
+ // We can't just use a &mut VecDeque<T, A>, as that would make Drain invariant over T
24
+ // and we want it to be covariant instead
28
25
deque : NonNull < VecDeque < T , A > > ,
29
- _phantom : PhantomData < & ' a T > ,
26
+ // drain_start is stored in deque.len
27
+ drain_len : usize ,
28
+ // index into the logical array, not the physical one (always lies in [0..deque.len))
29
+ idx : usize ,
30
+ // number of elements after the drain range
31
+ tail_len : usize ,
32
+ remaining : usize ,
33
+ // Needed to make Drain covariant over T
34
+ _marker : PhantomData < & ' a T > ,
30
35
}
31
36
32
37
impl < ' a , T , A : Allocator > Drain < ' a , T , A > {
33
38
pub ( super ) unsafe fn new (
34
- after_tail : usize ,
35
- after_head : usize ,
36
- ring : & ' a [ MaybeUninit < T > ] ,
37
- tail : usize ,
38
- head : usize ,
39
- deque : NonNull < VecDeque < T , A > > ,
39
+ deque : & ' a mut VecDeque < T , A > ,
40
+ drain_start : usize ,
41
+ drain_len : usize ,
40
42
) -> Self {
41
- let ring = unsafe { NonNull :: new_unchecked ( ring as * const [ MaybeUninit < T > ] as * mut _ ) } ;
42
- Drain { after_tail, after_head, ring, tail, head, deque, _phantom : PhantomData }
43
+ let orig_len = mem:: replace ( & mut deque. len , drain_start) ;
44
+ let tail_len = orig_len - drain_start - drain_len;
45
+ Drain {
46
+ deque : NonNull :: from ( deque) ,
47
+ drain_len,
48
+ idx : drain_start,
49
+ tail_len,
50
+ remaining : drain_len,
51
+ _marker : PhantomData ,
52
+ }
53
+ }
54
+
55
+ // Only returns pointers to the slices, as that's
56
+ // all we need to drop them
57
+ fn as_slices ( & self ) -> ( * mut [ T ] , * mut [ T ] ) {
58
+ unsafe {
59
+ let deque = self . deque . as_ref ( ) ;
60
+ let wrapped_start = deque. wrap_idx ( self . idx ) ;
61
+
62
+ if self . remaining <= deque. capacity ( ) - wrapped_start {
63
+ // there's only one contigous slice
64
+ (
65
+ ptr:: slice_from_raw_parts_mut ( deque. ptr ( ) . add ( wrapped_start) , self . remaining ) ,
66
+ & mut [ ] as * mut [ T ] ,
67
+ )
68
+ } else {
69
+ let head_len = deque. capacity ( ) - wrapped_start;
70
+ // this will never overflow due to the if condition
71
+ let tail_len = self . remaining - head_len;
72
+ (
73
+ ptr:: slice_from_raw_parts_mut ( deque. ptr ( ) . add ( wrapped_start) , head_len) ,
74
+ ptr:: slice_from_raw_parts_mut ( deque. ptr ( ) , tail_len) ,
75
+ )
76
+ }
77
+ }
43
78
}
44
79
}
45
80
46
81
#[ stable( feature = "collection_debug" , since = "1.17.0" ) ]
47
82
impl < T : fmt:: Debug , A : Allocator > fmt:: Debug for Drain < ' _ , T , A > {
48
83
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
49
84
f. debug_tuple ( "Drain" )
50
- . field ( & self . after_tail )
51
- . field ( & self . after_head )
52
- . field ( & self . ring )
53
- . field ( & self . tail )
54
- . field ( & self . head )
85
+ . field ( & self . drain_len )
86
+ . field ( & self . idx )
87
+ . field ( & self . tail_len )
88
+ . field ( & self . remaining )
55
89
. finish ( )
56
90
}
57
91
}
@@ -68,57 +102,77 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
68
102
69
103
impl < ' r , ' a , T , A : Allocator > Drop for DropGuard < ' r , ' a , T , A > {
70
104
fn drop ( & mut self ) {
71
- self . 0 . for_each ( drop) ;
105
+ if self . 0 . remaining != 0 {
106
+ let ( front, back) = self . 0 . as_slices ( ) ;
107
+ unsafe {
108
+ ptr:: drop_in_place ( front) ;
109
+ ptr:: drop_in_place ( back) ;
110
+ }
111
+ }
72
112
73
113
let source_deque = unsafe { self . 0 . deque . as_mut ( ) } ;
74
114
75
- // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head
76
- //
77
- // T t h H
78
- // [. . . o o x x o o . . .]
79
- //
80
- let orig_tail = source_deque. tail ;
81
- let drain_tail = source_deque. head ;
82
- let drain_head = self . 0 . after_tail ;
83
- let orig_head = self . 0 . after_head ;
115
+ let drain_start = source_deque. len ( ) ;
116
+ let drain_len = self . 0 . drain_len ;
117
+ let drain_end = drain_start + drain_len;
84
118
85
- let tail_len = count ( orig_tail, drain_tail, source_deque. cap ( ) ) ;
86
- let head_len = count ( drain_head, orig_head, source_deque. cap ( ) ) ;
119
+ let orig_len = self . 0 . tail_len + drain_end;
120
+
121
+ if T :: IS_ZST {
122
+ // no need to copy around any memory if T is a ZST
123
+ source_deque. len = orig_len - drain_len;
124
+ return ;
125
+ }
87
126
88
- // Restore the original head value
89
- source_deque . head = orig_head ;
127
+ let head_len = drain_start ;
128
+ let tail_len = self . 0 . tail_len ;
90
129
91
- match ( tail_len , head_len ) {
130
+ match ( head_len , tail_len ) {
92
131
( 0 , 0 ) => {
93
132
source_deque. head = 0 ;
94
- source_deque. tail = 0 ;
133
+ source_deque. len = 0 ;
95
134
}
96
135
( 0 , _) => {
97
- source_deque. tail = drain_head;
136
+ source_deque. head = source_deque. wrap_idx ( drain_len) ;
137
+ source_deque. len = orig_len - drain_len;
98
138
}
99
139
( _, 0 ) => {
100
- source_deque. head = drain_tail ;
140
+ source_deque. len = orig_len - drain_len ;
101
141
}
102
142
_ => unsafe {
103
- if tail_len <= head_len {
104
- source_deque. tail = source_deque. wrap_sub ( drain_head, tail_len) ;
105
- source_deque. wrap_copy ( source_deque. tail , orig_tail, tail_len) ;
143
+ if head_len <= tail_len {
144
+ source_deque. wrap_copy (
145
+ source_deque. head ,
146
+ source_deque. wrap_idx ( drain_len) ,
147
+ head_len,
148
+ ) ;
149
+ source_deque. head = source_deque. wrap_idx ( drain_len) ;
150
+ source_deque. len = orig_len - drain_len;
106
151
} else {
107
- source_deque. head = source_deque. wrap_add ( drain_tail, head_len) ;
108
- source_deque. wrap_copy ( drain_tail, drain_head, head_len) ;
152
+ source_deque. wrap_copy (
153
+ source_deque. wrap_idx ( head_len + drain_len) ,
154
+ source_deque. wrap_idx ( head_len) ,
155
+ tail_len,
156
+ ) ;
157
+ source_deque. len = orig_len - drain_len;
109
158
}
110
159
} ,
111
160
}
112
161
}
113
162
}
114
163
115
- while let Some ( item) = self . next ( ) {
116
- let guard = DropGuard ( self ) ;
117
- drop ( item) ;
118
- mem:: forget ( guard) ;
164
+ let guard = DropGuard ( self ) ;
165
+ let ( front, back) = guard. 0 . as_slices ( ) ;
166
+ unsafe {
167
+ // since idx is a logical index, we don't need to worry about wrapping.
168
+ guard. 0 . idx += front. len ( ) ;
169
+ guard. 0 . remaining -= front. len ( ) ;
170
+ ptr:: drop_in_place ( front) ;
171
+ guard. 0 . remaining = 0 ;
172
+ ptr:: drop_in_place ( back) ;
119
173
}
120
174
121
- DropGuard ( self ) ;
175
+ // Dropping `guard` handles moving the remaining elements into place.
122
176
}
123
177
}
124
178
@@ -128,20 +182,18 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
128
182
129
183
#[ inline]
130
184
fn next ( & mut self ) -> Option < T > {
131
- if self . tail == self . head {
185
+ if self . remaining == 0 {
132
186
return None ;
133
187
}
134
- let tail = self . tail ;
135
- self . tail = wrap_index ( self . tail . wrapping_add ( 1 ) , self . ring . len ( ) ) ;
136
- // Safety:
137
- // - `self.tail` in a ring buffer is always a valid index.
138
- // - `self.head` and `self.tail` equality is checked above.
139
- unsafe { Some ( ptr:: read ( self . ring . as_ptr ( ) . get_unchecked_mut ( tail) ) ) }
188
+ let wrapped_idx = unsafe { self . deque . as_ref ( ) . wrap_idx ( self . idx ) } ;
189
+ self . idx += 1 ;
190
+ self . remaining -= 1 ;
191
+ Some ( unsafe { self . deque . as_mut ( ) . buffer_read ( wrapped_idx) } )
140
192
}
141
193
142
194
#[ inline]
143
195
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
144
- let len = count ( self . tail , self . head , self . ring . len ( ) ) ;
196
+ let len = self . remaining ;
145
197
( len, Some ( len) )
146
198
}
147
199
}
@@ -150,14 +202,12 @@ impl<T, A: Allocator> Iterator for Drain<'_, T, A> {
150
202
impl < T , A : Allocator > DoubleEndedIterator for Drain < ' _ , T , A > {
151
203
#[ inline]
152
204
fn next_back ( & mut self ) -> Option < T > {
153
- if self . tail == self . head {
205
+ if self . remaining == 0 {
154
206
return None ;
155
207
}
156
- self . head = wrap_index ( self . head . wrapping_sub ( 1 ) , self . ring . len ( ) ) ;
157
- // Safety:
158
- // - `self.head` in a ring buffer is always a valid index.
159
- // - `self.head` and `self.tail` equality is checked above.
160
- unsafe { Some ( ptr:: read ( self . ring . as_ptr ( ) . get_unchecked_mut ( self . head ) ) ) }
208
+ self . remaining -= 1 ;
209
+ let wrapped_idx = unsafe { self . deque . as_ref ( ) . wrap_idx ( self . idx + self . remaining ) } ;
210
+ Some ( unsafe { self . deque . as_mut ( ) . buffer_read ( wrapped_idx) } )
161
211
}
162
212
}
163
213
0 commit comments