SList.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. //----------------------------------------------------------------------------
  6. //
  7. // File: SList.h
  8. //
  9. // Template for Singly Linked List
  10. //
  11. //----------------------------------------------------------------------------
  12. class FakeCount
  13. {
  14. protected:
  15. void IncrementCount() {}
  16. void DecrementCount() {}
  17. void SetCount(uint count) {}
  18. void AddCount(FakeCount& c) {}
  19. };
  20. class RealCount
  21. {
  22. protected:
  23. RealCount() : count(0) {}
  24. void IncrementCount() { count++; }
  25. void DecrementCount() { count--; }
  26. void SetCount(uint count) { this->count = count; }
  27. void AddCount(RealCount const& c) { this->count += c.Count(); }
  28. public:
  29. uint Count() const { return count; }
  30. private:
  31. uint count;
  32. };
  33. #if DBG
  34. typedef RealCount DefaultCount;
  35. #else
  36. typedef FakeCount DefaultCount;
  37. #endif
  38. template <typename TData, typename TCount = DefaultCount> class SListBase;
  39. template <typename TData> class SListNode;
  40. template <typename TData>
  41. class SListNodeBase
  42. {
  43. public:
  44. SListNodeBase<TData> * Next() const { return next.base; }
  45. SListNodeBase<TData> *& Next() { return next.base; }
  46. protected:
  47. // The next node can be a real node with data, or it point back to the start of the list
  48. // Use a union to show it in the debugger (instead of casting everywhere)
  49. union
  50. {
  51. SListNodeBase<TData> * base;
  52. SListNode<TData> * node;
  53. SListBase<TData> * list;
  54. } next;
  55. };
  56. template <typename TData>
  57. class SListNode : public SListNodeBase<TData>
  58. {
  59. friend class SListBase<TData, FakeCount>;
  60. friend class SListBase<TData, RealCount>;
  61. private:
  62. SListNode() : data() {}
  63. // Constructing with parameter
  64. template <typename TParam>
  65. SListNode(TParam param) : data(param) {}
  66. // Constructing with parameter
  67. template <typename TParam1, typename TParam2>
  68. SListNode(TParam1 param1, TParam2 param2) : data(param1, param2) {}
  69. // Constructing using copy constructor
  70. SListNode(TData const& data) : data(data) {};
  71. TData data;
  72. };
  73. template<typename TData, typename TCount>
  74. class SListBase : protected SListNodeBase<TData>, public TCount
  75. {
  76. private:
  77. typedef SListNodeBase<TData> NodeBase;
  78. typedef SListNode<TData> Node;
  79. bool IsHead(NodeBase const * node) const
  80. {
  81. return (node == this);
  82. }
  83. public:
  84. class Iterator
  85. {
  86. public:
  87. Iterator() : list(nullptr), current(nullptr) {}
  88. Iterator(SListBase const * list) : list(list), current(list) {};
  89. bool IsValid() const
  90. {
  91. return (current != nullptr && !list->IsHead(current));
  92. }
  93. void Reset()
  94. {
  95. current = list;
  96. }
  97. // forceinline only needed for SListBase<FlowEdge *, RealCount>::Iterator::Next()
  98. __forceinline
  99. bool Next()
  100. {
  101. Assert(current != nullptr);
  102. if (list->IsHead(current->Next()))
  103. {
  104. current = nullptr;
  105. return false;
  106. }
  107. current = current->Next();
  108. return true;
  109. }
  110. TData const& Data() const
  111. {
  112. Assert(this->IsValid());
  113. return ((Node *)current)->data;
  114. }
  115. TData& Data()
  116. {
  117. Assert(this->IsValid());
  118. return ((Node *)current)->data;
  119. }
  120. protected:
  121. SListBase const * list;
  122. NodeBase const * current;
  123. };
  124. class EditingIterator : public Iterator
  125. {
  126. public:
  127. EditingIterator() : Iterator(), last(nullptr) {};
  128. EditingIterator(SListBase * list) : Iterator(list), last(nullptr) {};
  129. bool Next()
  130. {
  131. if (last != nullptr && last->Next() != this->current)
  132. {
  133. this->current = last;
  134. }
  135. else
  136. {
  137. last = this->current;
  138. }
  139. return Iterator::Next();
  140. }
  141. void UnlinkCurrent()
  142. {
  143. UnlinkCurrentNode();
  144. }
  145. template <typename TAllocator>
  146. void RemoveCurrent(TAllocator * allocator)
  147. {
  148. const NodeBase *dead = this->current;
  149. UnlinkCurrent();
  150. auto freeFunc = TypeAllocatorFunc<TAllocator, TData>::GetFreeFunc();
  151. AllocatorFree(allocator, freeFunc, (Node *) dead, sizeof(Node));
  152. }
  153. template <typename TAllocator>
  154. TData * InsertNodeBefore(TAllocator * allocator)
  155. {
  156. Assert(last != nullptr);
  157. Node * newNode = AllocatorNew(TAllocator, allocator, Node);
  158. if (newNode)
  159. {
  160. newNode->Next() = last->Next();
  161. const_cast<NodeBase *>(last)->Next() = newNode;
  162. const_cast<SListBase *>(this->list)->IncrementCount();
  163. last = newNode;
  164. return &newNode->data;
  165. }
  166. return nullptr;
  167. }
  168. template <typename TAllocator>
  169. TData * InsertNodeBeforeNoThrow(TAllocator * allocator)
  170. {
  171. Assert(last != nullptr);
  172. Node * newNode = AllocatorNewNoThrow(TAllocator, allocator, Node);
  173. if (newNode)
  174. {
  175. newNode->Next() = last->Next();
  176. const_cast<NodeBase *>(last)->Next() = newNode;
  177. const_cast<SListBase *>(this->list)->IncrementCount();
  178. last = newNode;
  179. return &newNode->data;
  180. }
  181. return nullptr;
  182. }
  183. template <typename TAllocator>
  184. bool InsertBefore(TAllocator * allocator, TData const& data)
  185. {
  186. Assert(last != nullptr);
  187. Node * newNode = AllocatorNew(TAllocator, allocator, Node, data);
  188. if (newNode)
  189. {
  190. newNode->Next() = last->Next();
  191. const_cast<NodeBase *>(last)->Next() = newNode;
  192. const_cast<SListBase *>(this->list)->IncrementCount();
  193. last = newNode;
  194. return true;
  195. }
  196. return false;
  197. }
  198. void MoveCurrentTo(SListBase * toList)
  199. {
  200. NodeBase * node = UnlinkCurrentNode();
  201. node->Next() = toList->Next();
  202. toList->Next() = node;
  203. toList->IncrementCount();
  204. }
  205. private:
  206. NodeBase const * last;
  207. NodeBase * UnlinkCurrentNode()
  208. {
  209. NodeBase * unlinkedNode = const_cast<NodeBase *>(this->current);
  210. Assert(current != nullptr);
  211. Assert(!list->IsHead(this->current));
  212. Assert(last != nullptr);
  213. const_cast<NodeBase *>(last)->Next() = this->current->Next();
  214. this->current = last;
  215. last = nullptr;
  216. const_cast<SListBase *>(this->list)->DecrementCount();
  217. return unlinkedNode;
  218. }
  219. };
  220. explicit SListBase()
  221. {
  222. Reset();
  223. }
  224. ~SListBase()
  225. {
  226. AssertMsg(this->Empty(), "SListBase need to be cleared explicitly with an allocator");
  227. }
  228. void Reset()
  229. {
  230. this->Next() = this;
  231. this->SetCount(0);
  232. }
  233. template <typename TAllocator>
  234. __forceinline
  235. void Clear(TAllocator * allocator)
  236. {
  237. NodeBase * current = this->Next();
  238. while (!this->IsHead(current))
  239. {
  240. NodeBase * next = current->Next();
  241. auto freeFunc = TypeAllocatorFunc<TAllocator, TData>::GetFreeFunc();
  242. AllocatorFree(allocator, freeFunc, (Node *)current, sizeof(Node));
  243. current = next;
  244. }
  245. this->Reset();
  246. }
  247. bool Empty() const { return this->IsHead(this->Next()); }
  248. bool HasOne() const { return !Empty() && this->IsHead(this->Next()->Next()); }
  249. bool HasTwo() const { return !Empty() && this->IsHead(this->Next()->Next()->Next()); }
  250. TData const& Head() const { Assert(!Empty()); return ((Node *)this->Next())->data; }
  251. TData& Head()
  252. {
  253. Assert(!Empty());
  254. Node * node = this->next.node;
  255. return node->data;
  256. }
  257. template <typename TAllocator>
  258. bool Prepend(TAllocator * allocator, TData const& data)
  259. {
  260. Node * newNode = AllocatorNew(TAllocator, allocator, Node, data);
  261. if (newNode)
  262. {
  263. newNode->Next() = this->Next();
  264. this->Next() = newNode;
  265. this->IncrementCount();
  266. return true;
  267. }
  268. return false;
  269. }
  270. template <typename TAllocator>
  271. bool PrependNoThrow(TAllocator * allocator, TData const& data)
  272. {
  273. Node * newNode = AllocatorNewNoThrow(TAllocator, allocator, Node, data);
  274. if (newNode)
  275. {
  276. newNode->Next() = this->Next();
  277. this->Next() = newNode;
  278. this->IncrementCount();
  279. return true;
  280. }
  281. return false;
  282. }
  283. template <typename TAllocator>
  284. TData * PrependNode(TAllocator * allocator)
  285. {
  286. Node * newNode = AllocatorNew(TAllocator, allocator, Node);
  287. if (newNode)
  288. {
  289. newNode->Next() = this->Next();
  290. this->Next() = newNode;
  291. this->IncrementCount();
  292. return &newNode->data;
  293. }
  294. return nullptr;
  295. }
  296. template <typename TAllocator, typename TParam>
  297. TData * PrependNode(TAllocator * allocator, TParam param)
  298. {
  299. Node * newNode = AllocatorNew(TAllocator, allocator, Node, param);
  300. if (newNode)
  301. {
  302. newNode->Next() = this->Next();
  303. this->Next() = newNode;
  304. this->IncrementCount();
  305. return &newNode->data;
  306. }
  307. return nullptr;
  308. }
  309. template <typename TAllocator, typename TParam1, typename TParam2>
  310. TData * PrependNode(TAllocator * allocator, TParam1 param1, TParam2 param2)
  311. {
  312. Node * newNode = AllocatorNew(TAllocator, allocator, Node, param1, param2);
  313. if (newNode)
  314. {
  315. newNode->Next() = this->Next();
  316. this->Next() = newNode;
  317. this->IncrementCount();
  318. return &newNode->data;
  319. }
  320. return nullptr;
  321. }
  322. template <typename TAllocator>
  323. void RemoveHead(TAllocator * allocator)
  324. {
  325. Assert(!this->Empty());
  326. NodeBase * node = this->Next();
  327. this->Next() = node->Next();
  328. auto freeFunc = TypeAllocatorFunc<TAllocator, TData>::GetFreeFunc();
  329. AllocatorFree(allocator, freeFunc, (Node *) node, sizeof(Node));
  330. this->DecrementCount();
  331. }
  332. template <typename TAllocator>
  333. bool Remove(TAllocator * allocator, TData const& data)
  334. {
  335. EditingIterator iter(this);
  336. while (iter.Next())
  337. {
  338. if (iter.Data() == data)
  339. {
  340. iter.RemoveCurrent(allocator);
  341. return true;
  342. }
  343. }
  344. return false;
  345. }
  346. bool Has(TData data) const
  347. {
  348. Iterator iter(this);
  349. while (iter.Next())
  350. {
  351. if (iter.Data() == data)
  352. {
  353. return true;
  354. }
  355. }
  356. return false;
  357. }
  358. void MoveTo(SListBase * list)
  359. {
  360. while (!Empty())
  361. {
  362. this->MoveHeadTo(list);
  363. }
  364. }
  365. void MoveHeadTo(SListBase * list)
  366. {
  367. Assert(!this->Empty());
  368. NodeBase * node = this->Next();
  369. this->Next() = node->Next();
  370. node->Next() = list->Next();
  371. list->Next() = node;
  372. list->IncrementCount();
  373. this->DecrementCount();
  374. }
  375. // Moves the first element that satisfies the predicate to the toList
  376. template<class Fn>
  377. TData* MoveTo(SListBase* toList, Fn predicate)
  378. {
  379. Assert(this != toList);
  380. EditingIterator iter(this);
  381. while (iter.Next())
  382. {
  383. if (predicate(iter.Data()))
  384. {
  385. TData* data = &iter.Data();
  386. iter.MoveCurrentTo(toList);
  387. return data;
  388. }
  389. }
  390. return nullptr;
  391. }
  392. template<class Fn>
  393. TData* Find(Fn predicate)
  394. {
  395. Iterator iter(this);
  396. while(iter.Next())
  397. {
  398. if(predicate(iter.Data()))
  399. {
  400. return &iter.Data();
  401. }
  402. }
  403. return nullptr;
  404. }
  405. template<class Fn>
  406. void Iterate(Fn fn)
  407. {
  408. Iterator iter(this);
  409. while(iter.Next())
  410. {
  411. fn(iter.Data());
  412. }
  413. }
  414. void Reverse()
  415. {
  416. NodeBase * prev = this;
  417. NodeBase * current = this->Next();
  418. while (!this->IsHead(current))
  419. {
  420. NodeBase * next = current->Next();
  421. current->Next() = prev;
  422. prev = current;
  423. current = next;
  424. }
  425. current->Next() = prev;
  426. }
  427. bool Equals(SListBase const& other)
  428. {
  429. SListBase::Iterator iter(this);
  430. SListBase::Iterator iter2(&other);
  431. while (iter.Next())
  432. {
  433. if (!iter2.Next() || iter.Data() != iter2.Data())
  434. {
  435. return false;
  436. }
  437. }
  438. return !iter2.Next();
  439. }
  440. template <typename TAllocator>
  441. bool CopyTo(TAllocator * allocator, SListBase& to) const
  442. {
  443. return CopyTo<DefaultCopyElement>(allocator, to);
  444. }
  445. template <void (*CopyElement)(TData const& from, TData& to), typename TAllocator>
  446. bool CopyTo(TAllocator * allocator, SListBase& to) const
  447. {
  448. to.Clear(allocator);
  449. SListBase::Iterator iter(this);
  450. NodeBase ** next = &to.Next();
  451. while (iter.Next())
  452. {
  453. Node * node = AllocatorNew(TAllocator, allocator, Node);
  454. if (node == nullptr)
  455. {
  456. return false;
  457. }
  458. CopyElement(iter.Data(), node->data);
  459. *next = node;
  460. next = &node->Next();
  461. *next = &to; // Do this every time, in case an OOM exception occurs, to keep the list correct
  462. to.IncrementCount();
  463. }
  464. return true;
  465. }
  466. template <class Fn>
  467. void Map(Fn fn) const
  468. {
  469. MapUntil([fn](TData& data) { fn(data); return false; });
  470. }
  471. template <class Fn>
  472. bool MapUntil(Fn fn) const
  473. {
  474. Iterator iter(this);
  475. while (iter.Next())
  476. {
  477. if (fn(iter.Data()))
  478. {
  479. return true;
  480. }
  481. }
  482. return false;
  483. }
  484. private:
  485. static void DefaultCopyElement(TData const& from, TData& to) { to = from; }
  486. // disable copy constructor
  487. SListBase(SListBase const& list);
  488. };
  489. template <typename TData>
  490. class SListBaseCounted : public SListBase<TData, RealCount>
  491. {
  492. };
  493. template <typename TData, typename TAllocator = ArenaAllocator, typename TCount = DefaultCount>
  494. class SList : public SListBase<TData, TCount>
  495. {
  496. public:
  497. class EditingIterator : public SListBase<TData, TCount>::EditingIterator
  498. {
  499. public:
  500. EditingIterator() : SListBase<TData, TCount>::EditingIterator() {}
  501. EditingIterator(SList * list) : SListBase<TData, TCount>::EditingIterator(list) {}
  502. void RemoveCurrent()
  503. {
  504. __super::RemoveCurrent(Allocator());
  505. }
  506. TData * InsertNodeBefore()
  507. {
  508. return __super::InsertNodeBefore(Allocator());
  509. }
  510. bool InsertBefore(TData const& data)
  511. {
  512. return __super::InsertBefore(Allocator(), data);
  513. }
  514. private:
  515. TAllocator * Allocator() const
  516. {
  517. return ((SList const *)this->list)->allocator;
  518. }
  519. };
  520. explicit SList(TAllocator * allocator) : allocator(allocator) {}
  521. ~SList()
  522. {
  523. Clear();
  524. }
  525. void Clear()
  526. {
  527. __super::Clear(allocator);
  528. }
  529. bool Prepend(TData const& data)
  530. {
  531. return __super::Prepend(allocator, data);
  532. }
  533. TData * PrependNode()
  534. {
  535. return __super::PrependNode(allocator);
  536. }
  537. template <typename TParam>
  538. TData * PrependNode(TParam param)
  539. {
  540. return __super::PrependNode(allocator, param);
  541. }
  542. template <typename TParam1, typename TParam2>
  543. TData * PrependNode(TParam1 param1, TParam2 param2)
  544. {
  545. return __super::PrependNode(allocator, param1, param2);
  546. }
  547. void RemoveHead()
  548. {
  549. __super::RemoveHead(allocator);
  550. }
  551. bool Remove(TData const& data)
  552. {
  553. return __super::Remove(allocator, data);
  554. }
  555. // Stack like interface
  556. bool Push(TData const& data)
  557. {
  558. return Prepend(data);
  559. }
  560. TData Pop()
  561. {
  562. TData data = this->Head();
  563. RemoveHead();
  564. return data;
  565. }
  566. TData const& Top() const
  567. {
  568. return this->Head();
  569. }
  570. TData& Top()
  571. {
  572. return this->Head();
  573. }
  574. private:
  575. TAllocator * allocator;
  576. };
  577. template <typename TData, typename TAllocator = ArenaAllocator>
  578. class SListCounted : public SList<TData, TAllocator, RealCount>
  579. {
  580. public:
  581. explicit SListCounted(TAllocator * allocator) : SList<TData, TAllocator, RealCount>(allocator) {}
  582. };
  583. #define _FOREACH_LIST_ENTRY_EX(List, T, Iterator, iter, data, list) \
  584. List<T>::Iterator iter(list); \
  585. while (iter.Next()) \
  586. { \
  587. T& data = iter.Data();
  588. #define _NEXT_LIST_ENTRY_EX \
  589. }
  590. #define _FOREACH_LIST_ENTRY(List, T, data, list) { _FOREACH_LIST_ENTRY_EX(List, T, Iterator, __iter, data, list)
  591. #define _NEXT_LIST_ENTRY _NEXT_LIST_ENTRY_EX }
  592. #define FOREACH_SLISTBASE_ENTRY(T, data, list) _FOREACH_LIST_ENTRY(SListBase, T, data, list)
  593. #define NEXT_SLISTBASE_ENTRY _NEXT_LIST_ENTRY
  594. #define FOREACH_SLISTBASE_ENTRY_EDITING(T, data, list, iter) _FOREACH_LIST_ENTRY_EX(SListBase, T, EditingIterator, iter, data, list)
  595. #define NEXT_SLISTBASE_ENTRY_EDITING _NEXT_LIST_ENTRY_EX
  596. #define FOREACH_SLISTBASECOUNTED_ENTRY(T, data, list) _FOREACH_LIST_ENTRY(SListBaseCounted, T, data, list)
  597. #define NEXT_SLISTBASECOUNTED_ENTRY _NEXT_LIST_ENTRY
  598. #define FOREACH_SLISTBASECOUNTED_ENTRY_EDITING(T, data, list, iter) _FOREACH_LIST_ENTRY_EX(SListBaseCounted, T, EditingIterator, iter, data, list)
  599. #define NEXT_SLISTBASECOUNTED_ENTRY_EDITING _NEXT_LIST_ENTRY_EX
  600. #define FOREACH_SLIST_ENTRY(T, data, list) _FOREACH_LIST_ENTRY(SList, T, data, list)
  601. #define NEXT_SLIST_ENTRY _NEXT_LIST_ENTRY
  602. #define FOREACH_SLIST_ENTRY_EDITING(T, data, list, iter) _FOREACH_LIST_ENTRY_EX(SList, T, EditingIterator, iter, data, list)
  603. #define NEXT_SLIST_ENTRY_EDITING _NEXT_LIST_ENTRY_EX
  604. #define FOREACH_SLISTCOUNTED_ENTRY(T, data, list) _FOREACH_LIST_ENTRY(SListCounted, T, data, list)
  605. #define NEXT_SLISTCOUNTED_ENTRY _NEXT_LIST_ENTRY
  606. #define FOREACH_SLISTCOUNTED_ENTRY_EDITING(T, data, list, iter) _FOREACH_LIST_ENTRY_EX(SListCounted, T, EditingIterator, iter, data, list)
  607. #define NEXT_SLISTCOUNTED_ENTRY_EDITING _NEXT_LIST_ENTRY_EX