intrusive_red_black_tree.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include "common/common_funcs.h"
  5. #include "common/parent_of_member.h"
  6. #include "common/tree.h"
  7. namespace Common {
  8. namespace impl {
  9. class IntrusiveRedBlackTreeImpl;
  10. }
  11. #pragma pack(push, 4)
  12. struct IntrusiveRedBlackTreeNode {
  13. YUZU_NON_COPYABLE(IntrusiveRedBlackTreeNode);
  14. public:
  15. using RBEntry = freebsd::RBEntry<IntrusiveRedBlackTreeNode>;
  16. private:
  17. RBEntry m_entry;
  18. public:
  19. explicit IntrusiveRedBlackTreeNode() = default;
  20. [[nodiscard]] constexpr RBEntry& GetRBEntry() {
  21. return m_entry;
  22. }
  23. [[nodiscard]] constexpr const RBEntry& GetRBEntry() const {
  24. return m_entry;
  25. }
  26. constexpr void SetRBEntry(const RBEntry& entry) {
  27. m_entry = entry;
  28. }
  29. };
  30. static_assert(sizeof(IntrusiveRedBlackTreeNode) ==
  31. 3 * sizeof(void*) + std::max<size_t>(sizeof(freebsd::RBColor), 4));
  32. #pragma pack(pop)
  33. template <class T, class Traits, class Comparator>
  34. class IntrusiveRedBlackTree;
  35. namespace impl {
  36. class IntrusiveRedBlackTreeImpl {
  37. YUZU_NON_COPYABLE(IntrusiveRedBlackTreeImpl);
  38. private:
  39. template <class, class, class>
  40. friend class ::Common::IntrusiveRedBlackTree;
  41. private:
  42. using RootType = freebsd::RBHead<IntrusiveRedBlackTreeNode>;
  43. private:
  44. RootType m_root;
  45. public:
  46. template <bool Const>
  47. class Iterator;
  48. using value_type = IntrusiveRedBlackTreeNode;
  49. using size_type = size_t;
  50. using difference_type = ptrdiff_t;
  51. using pointer = value_type*;
  52. using const_pointer = const value_type*;
  53. using reference = value_type&;
  54. using const_reference = const value_type&;
  55. using iterator = Iterator<false>;
  56. using const_iterator = Iterator<true>;
  57. template <bool Const>
  58. class Iterator {
  59. public:
  60. using iterator_category = std::bidirectional_iterator_tag;
  61. using value_type = typename IntrusiveRedBlackTreeImpl::value_type;
  62. using difference_type = typename IntrusiveRedBlackTreeImpl::difference_type;
  63. using pointer = std::conditional_t<Const, IntrusiveRedBlackTreeImpl::const_pointer,
  64. IntrusiveRedBlackTreeImpl::pointer>;
  65. using reference = std::conditional_t<Const, IntrusiveRedBlackTreeImpl::const_reference,
  66. IntrusiveRedBlackTreeImpl::reference>;
  67. private:
  68. pointer m_node;
  69. public:
  70. constexpr explicit Iterator(pointer n) : m_node(n) {}
  71. constexpr bool operator==(const Iterator& rhs) const {
  72. return m_node == rhs.m_node;
  73. }
  74. constexpr bool operator!=(const Iterator& rhs) const {
  75. return !(*this == rhs);
  76. }
  77. constexpr pointer operator->() const {
  78. return m_node;
  79. }
  80. constexpr reference operator*() const {
  81. return *m_node;
  82. }
  83. constexpr Iterator& operator++() {
  84. m_node = GetNext(m_node);
  85. return *this;
  86. }
  87. constexpr Iterator& operator--() {
  88. m_node = GetPrev(m_node);
  89. return *this;
  90. }
  91. constexpr Iterator operator++(int) {
  92. const Iterator it{*this};
  93. ++(*this);
  94. return it;
  95. }
  96. constexpr Iterator operator--(int) {
  97. const Iterator it{*this};
  98. --(*this);
  99. return it;
  100. }
  101. constexpr operator Iterator<true>() const {
  102. return Iterator<true>(m_node);
  103. }
  104. };
  105. private:
  106. constexpr bool EmptyImpl() const {
  107. return m_root.IsEmpty();
  108. }
  109. constexpr IntrusiveRedBlackTreeNode* GetMinImpl() const {
  110. return freebsd::RB_MIN(const_cast<RootType&>(m_root));
  111. }
  112. constexpr IntrusiveRedBlackTreeNode* GetMaxImpl() const {
  113. return freebsd::RB_MAX(const_cast<RootType&>(m_root));
  114. }
  115. constexpr IntrusiveRedBlackTreeNode* RemoveImpl(IntrusiveRedBlackTreeNode* node) {
  116. return freebsd::RB_REMOVE(m_root, node);
  117. }
  118. public:
  119. static constexpr IntrusiveRedBlackTreeNode* GetNext(IntrusiveRedBlackTreeNode* node) {
  120. return freebsd::RB_NEXT(node);
  121. }
  122. static constexpr IntrusiveRedBlackTreeNode* GetPrev(IntrusiveRedBlackTreeNode* node) {
  123. return freebsd::RB_PREV(node);
  124. }
  125. static constexpr IntrusiveRedBlackTreeNode const* GetNext(
  126. IntrusiveRedBlackTreeNode const* node) {
  127. return static_cast<const IntrusiveRedBlackTreeNode*>(
  128. GetNext(const_cast<IntrusiveRedBlackTreeNode*>(node)));
  129. }
  130. static constexpr IntrusiveRedBlackTreeNode const* GetPrev(
  131. IntrusiveRedBlackTreeNode const* node) {
  132. return static_cast<const IntrusiveRedBlackTreeNode*>(
  133. GetPrev(const_cast<IntrusiveRedBlackTreeNode*>(node)));
  134. }
  135. public:
  136. constexpr IntrusiveRedBlackTreeImpl() = default;
  137. // Iterator accessors.
  138. constexpr iterator begin() {
  139. return iterator(this->GetMinImpl());
  140. }
  141. constexpr const_iterator begin() const {
  142. return const_iterator(this->GetMinImpl());
  143. }
  144. constexpr iterator end() {
  145. return iterator(static_cast<IntrusiveRedBlackTreeNode*>(nullptr));
  146. }
  147. constexpr const_iterator end() const {
  148. return const_iterator(static_cast<const IntrusiveRedBlackTreeNode*>(nullptr));
  149. }
  150. constexpr const_iterator cbegin() const {
  151. return this->begin();
  152. }
  153. constexpr const_iterator cend() const {
  154. return this->end();
  155. }
  156. constexpr iterator iterator_to(reference ref) {
  157. return iterator(std::addressof(ref));
  158. }
  159. constexpr const_iterator iterator_to(const_reference ref) const {
  160. return const_iterator(std::addressof(ref));
  161. }
  162. // Content management.
  163. constexpr bool empty() const {
  164. return this->EmptyImpl();
  165. }
  166. constexpr reference back() {
  167. return *this->GetMaxImpl();
  168. }
  169. constexpr const_reference back() const {
  170. return *this->GetMaxImpl();
  171. }
  172. constexpr reference front() {
  173. return *this->GetMinImpl();
  174. }
  175. constexpr const_reference front() const {
  176. return *this->GetMinImpl();
  177. }
  178. constexpr iterator erase(iterator it) {
  179. auto cur = std::addressof(*it);
  180. auto next = GetNext(cur);
  181. this->RemoveImpl(cur);
  182. return iterator(next);
  183. }
  184. };
  185. } // namespace impl
  186. template <typename T>
  187. concept HasRedBlackKeyType = requires {
  188. {
  189. std::is_same<typename T::RedBlackKeyType, void>::value
  190. } -> std::convertible_to<bool>;
  191. };
  192. namespace impl {
  193. template <typename T, typename Default>
  194. consteval auto* GetRedBlackKeyType() {
  195. if constexpr (HasRedBlackKeyType<T>) {
  196. return static_cast<typename T::RedBlackKeyType*>(nullptr);
  197. } else {
  198. return static_cast<Default*>(nullptr);
  199. }
  200. }
  201. } // namespace impl
  202. template <typename T, typename Default>
  203. using RedBlackKeyType = std::remove_pointer_t<decltype(impl::GetRedBlackKeyType<T, Default>())>;
  204. template <class T, class Traits, class Comparator>
  205. class IntrusiveRedBlackTree {
  206. YUZU_NON_COPYABLE(IntrusiveRedBlackTree);
  207. public:
  208. using ImplType = impl::IntrusiveRedBlackTreeImpl;
  209. private:
  210. ImplType m_impl;
  211. public:
  212. template <bool Const>
  213. class Iterator;
  214. using value_type = T;
  215. using size_type = size_t;
  216. using difference_type = ptrdiff_t;
  217. using pointer = T*;
  218. using const_pointer = const T*;
  219. using reference = T&;
  220. using const_reference = const T&;
  221. using iterator = Iterator<false>;
  222. using const_iterator = Iterator<true>;
  223. using key_type = RedBlackKeyType<Comparator, value_type>;
  224. using const_key_pointer = const key_type*;
  225. using const_key_reference = const key_type&;
  226. template <bool Const>
  227. class Iterator {
  228. public:
  229. friend class IntrusiveRedBlackTree<T, Traits, Comparator>;
  230. using ImplIterator =
  231. std::conditional_t<Const, ImplType::const_iterator, ImplType::iterator>;
  232. using iterator_category = std::bidirectional_iterator_tag;
  233. using value_type = typename IntrusiveRedBlackTree::value_type;
  234. using difference_type = typename IntrusiveRedBlackTree::difference_type;
  235. using pointer = std::conditional_t<Const, IntrusiveRedBlackTree::const_pointer,
  236. IntrusiveRedBlackTree::pointer>;
  237. using reference = std::conditional_t<Const, IntrusiveRedBlackTree::const_reference,
  238. IntrusiveRedBlackTree::reference>;
  239. private:
  240. ImplIterator m_impl;
  241. private:
  242. constexpr explicit Iterator(ImplIterator it) : m_impl(it) {}
  243. constexpr explicit Iterator(typename ImplIterator::pointer p) : m_impl(p) {}
  244. constexpr ImplIterator GetImplIterator() const {
  245. return m_impl;
  246. }
  247. public:
  248. constexpr bool operator==(const Iterator& rhs) const {
  249. return m_impl == rhs.m_impl;
  250. }
  251. constexpr bool operator!=(const Iterator& rhs) const {
  252. return !(*this == rhs);
  253. }
  254. constexpr pointer operator->() const {
  255. return Traits::GetParent(std::addressof(*m_impl));
  256. }
  257. constexpr reference operator*() const {
  258. return *Traits::GetParent(std::addressof(*m_impl));
  259. }
  260. constexpr Iterator& operator++() {
  261. ++m_impl;
  262. return *this;
  263. }
  264. constexpr Iterator& operator--() {
  265. --m_impl;
  266. return *this;
  267. }
  268. constexpr Iterator operator++(int) {
  269. const Iterator it{*this};
  270. ++m_impl;
  271. return it;
  272. }
  273. constexpr Iterator operator--(int) {
  274. const Iterator it{*this};
  275. --m_impl;
  276. return it;
  277. }
  278. constexpr operator Iterator<true>() const {
  279. return Iterator<true>(m_impl);
  280. }
  281. };
  282. private:
  283. static constexpr int CompareImpl(const IntrusiveRedBlackTreeNode* lhs,
  284. const IntrusiveRedBlackTreeNode* rhs) {
  285. return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs));
  286. }
  287. static constexpr int CompareKeyImpl(const_key_reference key,
  288. const IntrusiveRedBlackTreeNode* rhs) {
  289. return Comparator::Compare(key, *Traits::GetParent(rhs));
  290. }
  291. // Define accessors using RB_* functions.
  292. constexpr IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) {
  293. return freebsd::RB_INSERT(m_impl.m_root, node, CompareImpl);
  294. }
  295. constexpr IntrusiveRedBlackTreeNode* FindImpl(IntrusiveRedBlackTreeNode const* node) const {
  296. return freebsd::RB_FIND(const_cast<ImplType::RootType&>(m_impl.m_root),
  297. const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
  298. }
  299. constexpr IntrusiveRedBlackTreeNode* NFindImpl(IntrusiveRedBlackTreeNode const* node) const {
  300. return freebsd::RB_NFIND(const_cast<ImplType::RootType&>(m_impl.m_root),
  301. const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
  302. }
  303. constexpr IntrusiveRedBlackTreeNode* FindKeyImpl(const_key_reference key) const {
  304. return freebsd::RB_FIND_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key,
  305. CompareKeyImpl);
  306. }
  307. constexpr IntrusiveRedBlackTreeNode* NFindKeyImpl(const_key_reference key) const {
  308. return freebsd::RB_NFIND_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key,
  309. CompareKeyImpl);
  310. }
  311. constexpr IntrusiveRedBlackTreeNode* FindExistingImpl(
  312. IntrusiveRedBlackTreeNode const* node) const {
  313. return freebsd::RB_FIND_EXISTING(const_cast<ImplType::RootType&>(m_impl.m_root),
  314. const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
  315. }
  316. constexpr IntrusiveRedBlackTreeNode* FindExistingKeyImpl(const_key_reference key) const {
  317. return freebsd::RB_FIND_EXISTING_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key,
  318. CompareKeyImpl);
  319. }
  320. public:
  321. constexpr IntrusiveRedBlackTree() = default;
  322. // Iterator accessors.
  323. constexpr iterator begin() {
  324. return iterator(m_impl.begin());
  325. }
  326. constexpr const_iterator begin() const {
  327. return const_iterator(m_impl.begin());
  328. }
  329. constexpr iterator end() {
  330. return iterator(m_impl.end());
  331. }
  332. constexpr const_iterator end() const {
  333. return const_iterator(m_impl.end());
  334. }
  335. constexpr const_iterator cbegin() const {
  336. return this->begin();
  337. }
  338. constexpr const_iterator cend() const {
  339. return this->end();
  340. }
  341. constexpr iterator iterator_to(reference ref) {
  342. return iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
  343. }
  344. constexpr const_iterator iterator_to(const_reference ref) const {
  345. return const_iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
  346. }
  347. // Content management.
  348. constexpr bool empty() const {
  349. return m_impl.empty();
  350. }
  351. constexpr reference back() {
  352. return *Traits::GetParent(std::addressof(m_impl.back()));
  353. }
  354. constexpr const_reference back() const {
  355. return *Traits::GetParent(std::addressof(m_impl.back()));
  356. }
  357. constexpr reference front() {
  358. return *Traits::GetParent(std::addressof(m_impl.front()));
  359. }
  360. constexpr const_reference front() const {
  361. return *Traits::GetParent(std::addressof(m_impl.front()));
  362. }
  363. constexpr iterator erase(iterator it) {
  364. return iterator(m_impl.erase(it.GetImplIterator()));
  365. }
  366. constexpr iterator insert(reference ref) {
  367. ImplType::pointer node = Traits::GetNode(std::addressof(ref));
  368. this->InsertImpl(node);
  369. return iterator(node);
  370. }
  371. constexpr iterator find(const_reference ref) const {
  372. return iterator(this->FindImpl(Traits::GetNode(std::addressof(ref))));
  373. }
  374. constexpr iterator nfind(const_reference ref) const {
  375. return iterator(this->NFindImpl(Traits::GetNode(std::addressof(ref))));
  376. }
  377. constexpr iterator find_key(const_key_reference ref) const {
  378. return iterator(this->FindKeyImpl(ref));
  379. }
  380. constexpr iterator nfind_key(const_key_reference ref) const {
  381. return iterator(this->NFindKeyImpl(ref));
  382. }
  383. constexpr iterator find_existing(const_reference ref) const {
  384. return iterator(this->FindExistingImpl(Traits::GetNode(std::addressof(ref))));
  385. }
  386. constexpr iterator find_existing_key(const_key_reference ref) const {
  387. return iterator(this->FindExistingKeyImpl(ref));
  388. }
  389. };
  390. template <auto T, class Derived = Common::impl::GetParentType<T>>
  391. class IntrusiveRedBlackTreeMemberTraits;
  392. template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
  393. class IntrusiveRedBlackTreeMemberTraits<Member, Derived> {
  394. public:
  395. template <class Comparator>
  396. using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraits, Comparator>;
  397. using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
  398. private:
  399. template <class, class, class>
  400. friend class IntrusiveRedBlackTree;
  401. friend class impl::IntrusiveRedBlackTreeImpl;
  402. static constexpr IntrusiveRedBlackTreeNode* GetNode(Derived* parent) {
  403. return std::addressof(parent->*Member);
  404. }
  405. static constexpr IntrusiveRedBlackTreeNode const* GetNode(Derived const* parent) {
  406. return std::addressof(parent->*Member);
  407. }
  408. static Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
  409. return Common::GetParentPointer<Member, Derived>(node);
  410. }
  411. static Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) {
  412. return Common::GetParentPointer<Member, Derived>(node);
  413. }
  414. };
  415. template <auto T, class Derived = Common::impl::GetParentType<T>>
  416. class IntrusiveRedBlackTreeMemberTraitsDeferredAssert;
  417. template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
  418. class IntrusiveRedBlackTreeMemberTraitsDeferredAssert<Member, Derived> {
  419. public:
  420. template <class Comparator>
  421. using TreeType =
  422. IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert, Comparator>;
  423. using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
  424. private:
  425. template <class, class, class>
  426. friend class IntrusiveRedBlackTree;
  427. friend class impl::IntrusiveRedBlackTreeImpl;
  428. static constexpr IntrusiveRedBlackTreeNode* GetNode(Derived* parent) {
  429. return std::addressof(parent->*Member);
  430. }
  431. static constexpr IntrusiveRedBlackTreeNode const* GetNode(Derived const* parent) {
  432. return std::addressof(parent->*Member);
  433. }
  434. static Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
  435. return Common::GetParentPointer<Member, Derived>(node);
  436. }
  437. static Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) {
  438. return Common::GetParentPointer<Member, Derived>(node);
  439. }
  440. };
  441. template <class Derived>
  442. class alignas(void*) IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode {
  443. public:
  444. using IntrusiveRedBlackTreeNode::IntrusiveRedBlackTreeNode;
  445. constexpr Derived* GetPrev() {
  446. return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode*>(
  447. impl::IntrusiveRedBlackTreeImpl::GetPrev(this)));
  448. }
  449. constexpr const Derived* GetPrev() const {
  450. return static_cast<const Derived*>(static_cast<const IntrusiveRedBlackTreeBaseNode*>(
  451. impl::IntrusiveRedBlackTreeImpl::GetPrev(this)));
  452. }
  453. constexpr Derived* GetNext() {
  454. return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode*>(
  455. impl::IntrusiveRedBlackTreeImpl::GetNext(this)));
  456. }
  457. constexpr const Derived* GetNext() const {
  458. return static_cast<const Derived*>(static_cast<const IntrusiveRedBlackTreeBaseNode*>(
  459. impl::IntrusiveRedBlackTreeImpl::GetNext(this)));
  460. }
  461. };
  462. template <class Derived>
  463. class IntrusiveRedBlackTreeBaseTraits {
  464. public:
  465. template <class Comparator>
  466. using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeBaseTraits, Comparator>;
  467. using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
  468. private:
  469. template <class, class, class>
  470. friend class IntrusiveRedBlackTree;
  471. friend class impl::IntrusiveRedBlackTreeImpl;
  472. static constexpr IntrusiveRedBlackTreeNode* GetNode(Derived* parent) {
  473. return static_cast<IntrusiveRedBlackTreeNode*>(
  474. static_cast<IntrusiveRedBlackTreeBaseNode<Derived>*>(parent));
  475. }
  476. static constexpr IntrusiveRedBlackTreeNode const* GetNode(Derived const* parent) {
  477. return static_cast<const IntrusiveRedBlackTreeNode*>(
  478. static_cast<const IntrusiveRedBlackTreeBaseNode<Derived>*>(parent));
  479. }
  480. static constexpr Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
  481. return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode<Derived>*>(node));
  482. }
  483. static constexpr Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) {
  484. return static_cast<const Derived*>(
  485. static_cast<const IntrusiveRedBlackTreeBaseNode<Derived>*>(node));
  486. }
  487. };
  488. } // namespace Common