@@ -108,14 +108,18 @@ class MultiDList {
108
108
}
109
109
110
110
explicit Iterator (const MultiDList<T, HookPtr>& mlist,
111
- size_t listIdx) noexcept
111
+ size_t listIdx, bool head ) noexcept
112
112
: currIter_(mlist.lists_[mlist.lists_.size() - 1]->rbegin()),
113
113
mlist_(mlist) {
114
114
XDCHECK_LT (listIdx, mlist.lists_ .size ());
115
- initToValidRBeginFrom (listIdx);
115
+ if (head) {
116
+ initToValidBeginFrom (listIdx);
117
+ } else {
118
+ initToValidRBeginFrom (listIdx);
119
+ }
116
120
// We should either point to an element or the end() iterator
117
121
// which has an invalid index_.
118
- XDCHECK (index_ == kInvalidIndex || currIter_.get () != nullptr );
122
+ XDCHECK (index_ == kInvalidIndex || index_ == mlist. lists_ . size () || currIter_.get () != nullptr );
119
123
}
120
124
virtual ~Iterator () = default ;
121
125
@@ -167,6 +171,9 @@ class MultiDList {
167
171
168
172
// reset iterator to the beginning of a speicific queue
169
173
void initToValidRBeginFrom (size_t listIdx) noexcept ;
174
+
175
+ // reset iterator to the head of a specific queue
176
+ void initToValidBeginFrom (size_t listIdx) noexcept ;
170
177
171
178
// Index of current list
172
179
size_t index_{0 };
@@ -182,6 +189,9 @@ class MultiDList {
182
189
183
190
// provides an iterator starting from the tail of a specific list.
184
191
Iterator rbegin (size_t idx) const ;
192
+
193
+ // provides an iterator starting from the head of a specific list.
194
+ Iterator begin (size_t idx) const ;
185
195
186
196
// Iterator to compare against for the end.
187
197
Iterator rend () const noexcept ;
@@ -201,12 +211,26 @@ void MultiDList<T, HookPtr>::Iterator::goForward() noexcept {
201
211
}
202
212
// Move iterator forward
203
213
++currIter_;
204
- // If we land at the rend of this list, move to the previous list.
205
- while (index_ != kInvalidIndex &&
206
- currIter_ == mlist_.lists_ [index_]->rend ()) {
207
- --index_;
208
- if (index_ != kInvalidIndex ) {
209
- currIter_ = mlist_.lists_ [index_]->rbegin ();
214
+
215
+ if (currIter_.getDirection () == DListIterator::Direction::FROM_HEAD) {
216
+ // If we land at the rend of this list, move to the previous list.
217
+ while (index_ != kInvalidIndex && index_ != mlist_.lists_ .size () &&
218
+ currIter_ == mlist_.lists_ [index_]->end ()) {
219
+ ++index_;
220
+ if (index_ != kInvalidIndex && index_ != mlist_.lists_ .size ()) {
221
+ currIter_ = mlist_.lists_ [index_]->begin ();
222
+ } else {
223
+ return ;
224
+ }
225
+ }
226
+ } else {
227
+ // If we land at the rend of this list, move to the previous list.
228
+ while (index_ != kInvalidIndex &&
229
+ currIter_ == mlist_.lists_ [index_]->rend ()) {
230
+ --index_;
231
+ if (index_ != kInvalidIndex ) {
232
+ currIter_ = mlist_.lists_ [index_]->rbegin ();
233
+ }
210
234
}
211
235
}
212
236
}
@@ -247,6 +271,25 @@ void MultiDList<T, HookPtr>::Iterator::initToValidRBeginFrom(
247
271
: mlist_.lists_ [index_]->rbegin ();
248
272
}
249
273
274
+ template <typename T, DListHook<T> T::*HookPtr>
275
+ void MultiDList<T, HookPtr>::Iterator::initToValidBeginFrom(
276
+ size_t listIdx) noexcept {
277
+ // Find the first non-empty list.
278
+ index_ = listIdx;
279
+ while (index_ != mlist_.lists_ .size () &&
280
+ mlist_.lists_ [index_]->size () == 0 ) {
281
+ ++index_;
282
+ }
283
+ if (index_ == mlist_.lists_ .size ()) {
284
+ // we reached the end - we should get set to
285
+ // invalid index
286
+ index_ = std::numeric_limits<size_t >::max ();
287
+ }
288
+ currIter_ = index_ == std::numeric_limits<size_t >::max ()
289
+ ? mlist_.lists_ [0 ]->begin ()
290
+ : mlist_.lists_ [index_]->begin ();
291
+ }
292
+
250
293
template <typename T, DListHook<T> T::*HookPtr>
251
294
typename MultiDList<T, HookPtr>::Iterator&
252
295
MultiDList<T, HookPtr>::Iterator::operator ++() noexcept {
@@ -273,7 +316,16 @@ typename MultiDList<T, HookPtr>::Iterator MultiDList<T, HookPtr>::rbegin(
273
316
if (listIdx >= lists_.size ()) {
274
317
throw std::invalid_argument (" Invalid list index for MultiDList iterator." );
275
318
}
276
- return MultiDList<T, HookPtr>::Iterator (*this , listIdx);
319
+ return MultiDList<T, HookPtr>::Iterator (*this , listIdx, false );
320
+ }
321
+
322
+ template <typename T, DListHook<T> T::*HookPtr>
323
+ typename MultiDList<T, HookPtr>::Iterator MultiDList<T, HookPtr>::begin(
324
+ size_t listIdx) const {
325
+ if (listIdx >= lists_.size ()) {
326
+ throw std::invalid_argument (" Invalid list index for MultiDList iterator." );
327
+ }
328
+ return MultiDList<T, HookPtr>::Iterator (*this , listIdx, true );
277
329
}
278
330
279
331
template <typename T, DListHook<T> T::*HookPtr>
0 commit comments