intrlist.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. #pragma once
  2. #include "utility.h"
  3. #include <util/system/yassert.h>
  4. #include <iterator>
  5. struct TIntrusiveListDefaultTag {};
  6. /*
  7. * two-way linked list
  8. */
  9. template <class T, class Tag = TIntrusiveListDefaultTag>
  10. class TIntrusiveListItem {
  11. private:
  12. using TListItem = TIntrusiveListItem<T, Tag>;
  13. public:
  14. inline TIntrusiveListItem() noexcept
  15. : Next_(this)
  16. , Prev_(Next_)
  17. {
  18. }
  19. inline ~TIntrusiveListItem() {
  20. Unlink();
  21. }
  22. public:
  23. Y_PURE_FUNCTION inline bool Empty() const noexcept {
  24. return (Prev_ == this) && (Next_ == this);
  25. }
  26. inline void Unlink() noexcept {
  27. if (Empty()) {
  28. return;
  29. }
  30. Prev_->SetNext(Next_);
  31. Next_->SetPrev(Prev_);
  32. ResetItem();
  33. }
  34. inline void LinkBefore(TListItem* before) noexcept {
  35. Unlink();
  36. LinkBeforeNoUnlink(before);
  37. }
  38. inline void LinkBeforeNoUnlink(TListItem* before) noexcept {
  39. TListItem* const after = before->Prev();
  40. after->SetNext(this);
  41. SetPrev(after);
  42. SetNext(before);
  43. before->SetPrev(this);
  44. }
  45. inline void LinkBefore(TListItem& before) noexcept {
  46. LinkBefore(&before);
  47. }
  48. inline void LinkAfter(TListItem* after) noexcept {
  49. Unlink();
  50. LinkBeforeNoUnlink(after->Next());
  51. }
  52. inline void LinkAfter(TListItem& after) noexcept {
  53. LinkAfter(&after);
  54. }
  55. public:
  56. inline TListItem* Prev() noexcept {
  57. return Prev_;
  58. }
  59. inline const TListItem* Prev() const noexcept {
  60. return Prev_;
  61. }
  62. inline TListItem* Next() noexcept {
  63. return Next_;
  64. }
  65. inline const TListItem* Next() const noexcept {
  66. return Next_;
  67. }
  68. public:
  69. inline void SetNext(TListItem* item) noexcept {
  70. Next_ = item;
  71. }
  72. inline void SetPrev(TListItem* item) noexcept {
  73. Prev_ = item;
  74. }
  75. public:
  76. inline T* Node() noexcept {
  77. return static_cast<T*>(this);
  78. }
  79. inline const T* Node() const noexcept {
  80. return static_cast<const T*>(this);
  81. }
  82. public:
  83. // NB(arkady-e1ppa): These methods are used to implement
  84. // intrusive lock-free algorithms which want to natively
  85. // interact with TIntrusiveList.
  86. // Assume that if you've used MutableNext/MutablePrev
  87. // methods, you are not safe to use anything but
  88. // MutableNext/MutablePrev/ResetItem methods until
  89. // you call a ResetItem method.
  90. inline TListItem*& MutableNext() noexcept {
  91. return Next_;
  92. }
  93. inline TListItem*& MutablePrev() noexcept {
  94. return Prev_;
  95. }
  96. inline void ResetItem() noexcept {
  97. Next_ = this;
  98. Prev_ = Next_;
  99. }
  100. private:
  101. inline TIntrusiveListItem(const TIntrusiveListItem&) = delete;
  102. inline TIntrusiveListItem& operator=(const TIntrusiveListItem&) = delete;
  103. private:
  104. TListItem* Next_;
  105. TListItem* Prev_;
  106. };
  107. template <class T, class Tag>
  108. class TIntrusiveList {
  109. private:
  110. using TListItem = TIntrusiveListItem<T, Tag>;
  111. template <class TListItem, class TNode>
  112. class TIteratorBase {
  113. public:
  114. using TItem = TListItem;
  115. using TReference = TNode&;
  116. using TPointer = TNode*;
  117. using iterator_category = std::bidirectional_iterator_tag;
  118. using difference_type = ptrdiff_t;
  119. using value_type = TNode;
  120. using reference = TReference;
  121. using pointer = TPointer;
  122. inline TIteratorBase() noexcept
  123. : Item_(nullptr)
  124. {
  125. }
  126. template <class TListItem_, class TNode_>
  127. inline TIteratorBase(const TIteratorBase<TListItem_, TNode_>& right) noexcept
  128. : Item_(right.Item())
  129. {
  130. }
  131. inline TIteratorBase(TItem* item) noexcept
  132. : Item_(item)
  133. {
  134. }
  135. inline TItem* Item() const noexcept {
  136. return Item_;
  137. }
  138. inline void Next() noexcept {
  139. Item_ = Item_->Next();
  140. }
  141. inline void Prev() noexcept {
  142. Item_ = Item_->Prev();
  143. }
  144. template <class TListItem_, class TNode_>
  145. inline bool operator==(const TIteratorBase<TListItem_, TNode_>& right) const noexcept {
  146. return Item() == right.Item();
  147. }
  148. template <class TListItem_, class TNode_>
  149. inline bool operator!=(const TIteratorBase<TListItem_, TNode_>& right) const noexcept {
  150. return Item() != right.Item();
  151. }
  152. inline TIteratorBase& operator++() noexcept {
  153. Next();
  154. return *this;
  155. }
  156. inline TIteratorBase operator++(int) noexcept {
  157. TIteratorBase ret(*this);
  158. Next();
  159. return ret;
  160. }
  161. inline TIteratorBase& operator--() noexcept {
  162. Prev();
  163. return *this;
  164. }
  165. inline TIteratorBase operator--(int) noexcept {
  166. TIteratorBase ret(*this);
  167. Prev();
  168. return ret;
  169. }
  170. inline TReference operator*() const noexcept {
  171. return *Item_->Node();
  172. }
  173. inline TPointer operator->() const noexcept {
  174. return Item_->Node();
  175. }
  176. private:
  177. TItem* Item_;
  178. };
  179. template <class TIterator>
  180. class TReverseIteratorBase {
  181. public:
  182. using TItem = typename TIterator::TItem;
  183. using TReference = typename TIterator::TReference;
  184. using TPointer = typename TIterator::TPointer;
  185. using iterator_category = typename TIterator::iterator_category;
  186. using difference_type = typename TIterator::difference_type;
  187. using value_type = typename TIterator::value_type;
  188. using reference = typename TIterator::reference;
  189. using pointer = typename TIterator::pointer;
  190. inline TReverseIteratorBase() noexcept = default;
  191. template <class TIterator_>
  192. inline TReverseIteratorBase(const TReverseIteratorBase<TIterator_>& right) noexcept
  193. : Current_(right.Base())
  194. {
  195. }
  196. inline explicit TReverseIteratorBase(TIterator item) noexcept
  197. : Current_(item)
  198. {
  199. }
  200. inline TIterator Base() const noexcept {
  201. return Current_;
  202. }
  203. inline TItem* Item() const noexcept {
  204. TIterator ret = Current_;
  205. return (--ret).Item();
  206. }
  207. inline void Next() noexcept {
  208. Current_.Prev();
  209. }
  210. inline void Prev() noexcept {
  211. Current_.Next();
  212. }
  213. template <class TIterator_>
  214. inline bool operator==(const TReverseIteratorBase<TIterator_>& right) const noexcept {
  215. return Base() == right.Base();
  216. }
  217. template <class TIterator_>
  218. inline bool operator!=(const TReverseIteratorBase<TIterator_>& right) const noexcept {
  219. return Base() != right.Base();
  220. }
  221. inline TReverseIteratorBase& operator++() noexcept {
  222. Next();
  223. return *this;
  224. }
  225. inline TReverseIteratorBase operator++(int) noexcept {
  226. TReverseIteratorBase ret(*this);
  227. Next();
  228. return ret;
  229. }
  230. inline TReverseIteratorBase& operator--() noexcept {
  231. Prev();
  232. return *this;
  233. }
  234. inline TReverseIteratorBase operator--(int) noexcept {
  235. TReverseIteratorBase ret(*this);
  236. Prev();
  237. return ret;
  238. }
  239. inline TReference operator*() const noexcept {
  240. TIterator ret = Current_;
  241. return *--ret;
  242. }
  243. inline TPointer operator->() const noexcept {
  244. TIterator ret = Current_;
  245. return &*--ret;
  246. }
  247. private:
  248. TIterator Current_;
  249. };
  250. public:
  251. using TIterator = TIteratorBase<TListItem, T>;
  252. using TConstIterator = TIteratorBase<const TListItem, const T>;
  253. using TReverseIterator = TReverseIteratorBase<TIterator>;
  254. using TConstReverseIterator = TReverseIteratorBase<TConstIterator>;
  255. using iterator = TIterator;
  256. using const_iterator = TConstIterator;
  257. using reverse_iterator = TReverseIterator;
  258. using const_reverse_iterator = TConstReverseIterator;
  259. public:
  260. inline void Swap(TIntrusiveList& right) noexcept {
  261. TIntrusiveList temp;
  262. temp.Append(right);
  263. Y_ASSERT(right.Empty());
  264. right.Append(*this);
  265. Y_ASSERT(this->Empty());
  266. this->Append(temp);
  267. Y_ASSERT(temp.Empty());
  268. }
  269. public:
  270. inline TIntrusiveList() noexcept = default;
  271. inline ~TIntrusiveList() = default;
  272. inline TIntrusiveList(TIntrusiveList&& right) noexcept {
  273. this->Swap(right);
  274. }
  275. inline TIntrusiveList& operator=(TIntrusiveList&& rhs) noexcept {
  276. this->Swap(rhs);
  277. return *this;
  278. }
  279. inline explicit operator bool() const noexcept {
  280. return !Empty();
  281. }
  282. Y_PURE_FUNCTION inline bool Empty() const noexcept {
  283. return End_.Empty();
  284. }
  285. inline size_t Size() const noexcept {
  286. return std::distance(Begin(), End());
  287. }
  288. inline void Remove(TListItem* item) noexcept {
  289. item->Unlink();
  290. }
  291. inline void Clear() noexcept {
  292. End_.Unlink();
  293. }
  294. public:
  295. inline TIterator Begin() noexcept {
  296. return ++End();
  297. }
  298. inline TIterator End() noexcept {
  299. return TIterator(&End_);
  300. }
  301. inline TConstIterator Begin() const noexcept {
  302. return ++End();
  303. }
  304. inline TConstIterator End() const noexcept {
  305. return TConstIterator(&End_);
  306. }
  307. inline TReverseIterator RBegin() noexcept {
  308. return TReverseIterator(End());
  309. }
  310. inline TReverseIterator REnd() noexcept {
  311. return TReverseIterator(Begin());
  312. }
  313. inline TConstReverseIterator RBegin() const noexcept {
  314. return TConstReverseIterator(End());
  315. }
  316. inline TConstReverseIterator REnd() const noexcept {
  317. return TConstReverseIterator(Begin());
  318. }
  319. inline TConstIterator CBegin() const noexcept {
  320. return Begin();
  321. }
  322. inline TConstIterator CEnd() const noexcept {
  323. return End();
  324. }
  325. inline TConstReverseIterator CRBegin() const noexcept {
  326. return RBegin();
  327. }
  328. inline TConstReverseIterator CREnd() const noexcept {
  329. return REnd();
  330. }
  331. public:
  332. inline iterator begin() noexcept {
  333. return Begin();
  334. }
  335. inline iterator end() noexcept {
  336. return End();
  337. }
  338. inline const_iterator begin() const noexcept {
  339. return Begin();
  340. }
  341. inline const_iterator end() const noexcept {
  342. return End();
  343. }
  344. inline reverse_iterator rbegin() noexcept {
  345. return RBegin();
  346. }
  347. inline reverse_iterator rend() noexcept {
  348. return REnd();
  349. }
  350. inline const_iterator cbegin() const noexcept {
  351. return CBegin();
  352. }
  353. inline const_iterator cend() const noexcept {
  354. return CEnd();
  355. }
  356. inline const_reverse_iterator crbegin() const noexcept {
  357. return CRBegin();
  358. }
  359. inline const_reverse_iterator crend() const noexcept {
  360. return CREnd();
  361. }
  362. public:
  363. inline T* Back() noexcept {
  364. return End_.Prev()->Node();
  365. }
  366. inline T* Front() noexcept {
  367. return End_.Next()->Node();
  368. }
  369. inline const T* Back() const noexcept {
  370. return End_.Prev()->Node();
  371. }
  372. inline const T* Front() const noexcept {
  373. return End_.Next()->Node();
  374. }
  375. inline void PushBack(TListItem* item) noexcept {
  376. item->LinkBefore(End_);
  377. }
  378. inline void PushFront(TListItem* item) noexcept {
  379. item->LinkAfter(End_);
  380. }
  381. inline T* PopBack() noexcept {
  382. TListItem* const ret = End_.Prev();
  383. ret->Unlink();
  384. return ret->Node();
  385. }
  386. inline T* PopFront() noexcept {
  387. TListItem* const ret = End_.Next();
  388. ret->Unlink();
  389. return ret->Node();
  390. }
  391. inline void Append(TIntrusiveList& list) noexcept {
  392. Cut(list.Begin(), list.End(), End());
  393. }
  394. inline void Append(TIntrusiveList&& list) noexcept {
  395. Append(list);
  396. }
  397. inline static void Cut(TIterator begin, TIterator end, TIterator pasteBefore) noexcept {
  398. if (begin == end) {
  399. return;
  400. }
  401. TListItem* const cutFront = begin.Item();
  402. TListItem* const gapBack = end.Item();
  403. TListItem* const gapFront = cutFront->Prev();
  404. TListItem* const cutBack = gapBack->Prev();
  405. gapFront->SetNext(gapBack);
  406. gapBack->SetPrev(gapFront);
  407. TListItem* const pasteBack = pasteBefore.Item();
  408. TListItem* const pasteFront = pasteBack->Prev();
  409. pasteFront->SetNext(cutFront);
  410. cutFront->SetPrev(pasteFront);
  411. cutBack->SetNext(pasteBack);
  412. pasteBack->SetPrev(cutBack);
  413. }
  414. public:
  415. template <class TFunctor>
  416. inline void ForEach(TFunctor&& functor) {
  417. TIterator i = Begin();
  418. while (i != End()) {
  419. functor(&*(i++));
  420. }
  421. }
  422. template <class TFunctor>
  423. inline void ForEach(TFunctor&& functor) const {
  424. TConstIterator i = Begin();
  425. while (i != End()) {
  426. functor(&*(i++));
  427. }
  428. }
  429. template <class TComparer>
  430. inline void QuickSort(TComparer&& comparer) {
  431. if (Begin() == End() || ++Begin() == End()) {
  432. return;
  433. }
  434. T* const pivot = PopFront();
  435. TIntrusiveList bigger;
  436. TIterator i = Begin();
  437. while (i != End()) {
  438. if (comparer(*pivot, *i)) {
  439. bigger.PushBack(&*i++);
  440. } else {
  441. ++i;
  442. }
  443. }
  444. this->QuickSort(comparer);
  445. bigger.QuickSort(comparer);
  446. PushBack(pivot);
  447. Append(bigger);
  448. }
  449. private:
  450. inline TIntrusiveList(const TIntrusiveList&) = delete;
  451. inline TIntrusiveList& operator=(const TIntrusiveList&) = delete;
  452. private:
  453. TListItem End_;
  454. };
  455. template <class T, class D, class Tag>
  456. class TIntrusiveListWithAutoDelete: public TIntrusiveList<T, Tag> {
  457. public:
  458. using TIterator = typename TIntrusiveList<T, Tag>::TIterator;
  459. using TConstIterator = typename TIntrusiveList<T, Tag>::TConstIterator;
  460. using TReverseIterator = typename TIntrusiveList<T, Tag>::TReverseIterator;
  461. using TConstReverseIterator = typename TIntrusiveList<T, Tag>::TConstReverseIterator;
  462. using iterator = TIterator;
  463. using const_iterator = TConstIterator;
  464. using reverse_iterator = TReverseIterator;
  465. using const_reverse_iterator = TConstReverseIterator;
  466. public:
  467. inline TIntrusiveListWithAutoDelete() noexcept = default;
  468. inline TIntrusiveListWithAutoDelete(TIntrusiveListWithAutoDelete&& right) noexcept
  469. : TIntrusiveList<T, Tag>(std::move(right))
  470. {
  471. }
  472. inline ~TIntrusiveListWithAutoDelete() {
  473. this->Clear();
  474. }
  475. TIntrusiveListWithAutoDelete& operator=(TIntrusiveListWithAutoDelete&& rhs) noexcept {
  476. TIntrusiveList<T, Tag>::operator=(std::move(rhs));
  477. return *this;
  478. }
  479. public:
  480. inline void Clear() noexcept {
  481. this->ForEach([](auto* item) {
  482. D::Destroy(item);
  483. });
  484. }
  485. inline static void Cut(TIterator begin, TIterator end) noexcept {
  486. TIntrusiveListWithAutoDelete<T, D, Tag> temp;
  487. Cut(begin, end, temp.End());
  488. }
  489. inline static void Cut(TIterator begin, TIterator end, TIterator pasteBefore) noexcept {
  490. TIntrusiveList<T, Tag>::Cut(begin, end, pasteBefore);
  491. }
  492. };
  493. /*
  494. * one-way linked list
  495. */
  496. template <class T, class Tag = TIntrusiveListDefaultTag>
  497. class TIntrusiveSListItem {
  498. private:
  499. using TListItem = TIntrusiveSListItem<T, Tag>;
  500. public:
  501. inline TIntrusiveSListItem() noexcept
  502. : Next_(nullptr)
  503. {
  504. }
  505. inline ~TIntrusiveSListItem() = default;
  506. inline bool IsEnd() const noexcept {
  507. return Next_ == nullptr;
  508. }
  509. inline TListItem* Next() noexcept {
  510. return Next_;
  511. }
  512. inline const TListItem* Next() const noexcept {
  513. return Next_;
  514. }
  515. inline void SetNext(TListItem* item) noexcept {
  516. Next_ = item;
  517. }
  518. public:
  519. inline T* Node() noexcept {
  520. return static_cast<T*>(this);
  521. }
  522. inline const T* Node() const noexcept {
  523. return static_cast<const T*>(this);
  524. }
  525. private:
  526. TListItem* Next_;
  527. };
  528. template <class T, class Tag>
  529. class TIntrusiveSList {
  530. private:
  531. using TListItem = TIntrusiveSListItem<T, Tag>;
  532. public:
  533. template <class TListItem, class TNode>
  534. class TIteratorBase {
  535. public:
  536. using TItem = TListItem;
  537. using TReference = TNode&;
  538. using TPointer = TNode*;
  539. using difference_type = std::ptrdiff_t;
  540. using value_type = TNode;
  541. using pointer = TPointer;
  542. using reference = TReference;
  543. using iterator_category = std::forward_iterator_tag;
  544. inline TIteratorBase(TListItem* item) noexcept
  545. : Item_(item)
  546. {
  547. }
  548. inline void Next() noexcept {
  549. Item_ = Item_->Next();
  550. }
  551. inline bool operator==(const TIteratorBase& right) const noexcept {
  552. return Item_ == right.Item_;
  553. }
  554. inline bool operator!=(const TIteratorBase& right) const noexcept {
  555. return Item_ != right.Item_;
  556. }
  557. inline TIteratorBase& operator++() noexcept {
  558. Next();
  559. return *this;
  560. }
  561. inline TIteratorBase operator++(int) noexcept {
  562. TIteratorBase ret(*this);
  563. Next();
  564. return ret;
  565. }
  566. inline TNode& operator*() noexcept {
  567. return *Item_->Node();
  568. }
  569. inline TNode* operator->() noexcept {
  570. return Item_->Node();
  571. }
  572. private:
  573. TListItem* Item_;
  574. };
  575. public:
  576. using TIterator = TIteratorBase<TListItem, T>;
  577. using TConstIterator = TIteratorBase<const TListItem, const T>;
  578. using iterator = TIterator;
  579. using const_iterator = TConstIterator;
  580. public:
  581. inline TIntrusiveSList() noexcept
  582. : Begin_(nullptr)
  583. {
  584. }
  585. inline void Swap(TIntrusiveSList& right) noexcept {
  586. DoSwap(Begin_, right.Begin_);
  587. }
  588. inline explicit operator bool() const noexcept {
  589. return !Empty();
  590. }
  591. Y_PURE_FUNCTION inline bool Empty() const noexcept {
  592. return Begin_ == nullptr;
  593. }
  594. inline size_t Size() const noexcept {
  595. return std::distance(Begin(), End());
  596. }
  597. inline void Clear() noexcept {
  598. Begin_ = nullptr;
  599. }
  600. inline TIterator Begin() noexcept {
  601. return TIterator(Begin_);
  602. }
  603. inline TIterator End() noexcept {
  604. return TIterator(nullptr);
  605. }
  606. inline TConstIterator Begin() const noexcept {
  607. return TConstIterator(Begin_);
  608. }
  609. inline TConstIterator End() const noexcept {
  610. return TConstIterator(nullptr);
  611. }
  612. inline TConstIterator CBegin() const noexcept {
  613. return Begin();
  614. }
  615. inline TConstIterator CEnd() const noexcept {
  616. return End();
  617. }
  618. // compat methods
  619. inline iterator begin() noexcept {
  620. return Begin();
  621. }
  622. inline iterator end() noexcept {
  623. return End();
  624. }
  625. inline const_iterator begin() const noexcept {
  626. return Begin();
  627. }
  628. inline const_iterator end() const noexcept {
  629. return End();
  630. }
  631. inline const_iterator cbegin() const noexcept {
  632. return CBegin();
  633. }
  634. inline const_iterator cend() const noexcept {
  635. return CEnd();
  636. }
  637. inline T* Front() noexcept {
  638. Y_ASSERT(Begin_);
  639. return Begin_->Node();
  640. }
  641. inline const T* Front() const noexcept {
  642. Y_ASSERT(Begin_);
  643. return Begin_->Node();
  644. }
  645. inline void PushFront(TListItem* item) noexcept {
  646. item->SetNext(Begin_);
  647. Begin_ = item;
  648. }
  649. inline T* PopFront() noexcept {
  650. Y_ASSERT(Begin_);
  651. TListItem* const ret = Begin_;
  652. Begin_ = Begin_->Next();
  653. return ret->Node();
  654. }
  655. inline void Reverse() noexcept {
  656. TIntrusiveSList temp;
  657. while (!Empty()) {
  658. temp.PushFront(PopFront());
  659. }
  660. this->Swap(temp);
  661. }
  662. template <class TFunctor>
  663. inline void ForEach(TFunctor&& functor) const noexcept(noexcept(functor(std::declval<TListItem>().Node()))) {
  664. TListItem* i = Begin_;
  665. while (i) {
  666. TListItem* const next = i->Next();
  667. functor(i->Node());
  668. i = next;
  669. }
  670. }
  671. private:
  672. TListItem* Begin_;
  673. };