@@ -108,14 +108,18 @@ class MultiDList {
108108 }
109109
110110 explicit Iterator (const MultiDList<T, HookPtr>& mlist,
111- size_t listIdx) noexcept
111+ size_t listIdx, bool head ) noexcept
112112 : currIter_(mlist.lists_[mlist.lists_.size() - 1]->rbegin()),
113113 mlist_(mlist) {
114114 XDCHECK_LT (listIdx, mlist.lists_ .size ());
115- initToValidRBeginFrom (listIdx);
115+ if (head) {
116+ initToValidBeginFrom (listIdx);
117+ } else {
118+ initToValidRBeginFrom (listIdx);
119+ }
116120 // We should either point to an element or the end() iterator
117121 // which has an invalid index_.
118- XDCHECK (index_ == kInvalidIndex || currIter_.get () != nullptr );
122+ XDCHECK (index_ == kInvalidIndex || index_ == mlist. lists_ . size () || currIter_.get () != nullptr );
119123 }
120124 virtual ~Iterator () = default ;
121125
@@ -167,6 +171,9 @@ class MultiDList {
167171
168172 // reset iterator to the beginning of a speicific queue
169173 void initToValidRBeginFrom (size_t listIdx) noexcept ;
174+
175+ // reset iterator to the head of a specific queue
176+ void initToValidBeginFrom (size_t listIdx) noexcept ;
170177
171178 // Index of current list
172179 size_t index_{0 };
@@ -182,6 +189,9 @@ class MultiDList {
182189
183190 // provides an iterator starting from the tail of a specific list.
184191 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 ;
185195
186196 // Iterator to compare against for the end.
187197 Iterator rend () const noexcept ;
@@ -201,12 +211,26 @@ void MultiDList<T, HookPtr>::Iterator::goForward() noexcept {
201211 }
202212 // Move iterator forward
203213 ++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+ }
210234 }
211235 }
212236}
@@ -247,6 +271,25 @@ void MultiDList<T, HookPtr>::Iterator::initToValidRBeginFrom(
247271 : mlist_.lists_ [index_]->rbegin ();
248272}
249273
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+
250293template <typename T, DListHook<T> T::*HookPtr>
251294typename MultiDList<T, HookPtr>::Iterator&
252295MultiDList<T, HookPtr>::Iterator::operator ++() noexcept {
@@ -273,7 +316,16 @@ typename MultiDList<T, HookPtr>::Iterator MultiDList<T, HookPtr>::rbegin(
273316 if (listIdx >= lists_.size ()) {
274317 throw std::invalid_argument (" Invalid list index for MultiDList iterator." );
275318 }
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 );
277329}
278330
279331template <typename T, DListHook<T> T::*HookPtr>
0 commit comments