intrlist.h 19 KB

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