intrusive_red_black_tree.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  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. { std::is_same<typename T::RedBlackKeyType, void>::value } -> std::convertible_to<bool>;
  189. };
  190. namespace impl {
  191. template <typename T, typename Default>
  192. consteval auto* GetRedBlackKeyType() {
  193. if constexpr (HasRedBlackKeyType<T>) {
  194. return static_cast<typename T::RedBlackKeyType*>(nullptr);
  195. } else {
  196. return static_cast<Default*>(nullptr);
  197. }
  198. }
  199. } // namespace impl
  200. template <typename T, typename Default>
  201. using RedBlackKeyType = std::remove_pointer_t<decltype(impl::GetRedBlackKeyType<T, Default>())>;
  202. template <class T, class Traits, class Comparator>
  203. class IntrusiveRedBlackTree {
  204. YUZU_NON_COPYABLE(IntrusiveRedBlackTree);
  205. public:
  206. using ImplType = impl::IntrusiveRedBlackTreeImpl;
  207. private:
  208. ImplType m_impl;
  209. public:
  210. template <bool Const>
  211. class Iterator;
  212. using value_type = T;
  213. using size_type = size_t;
  214. using difference_type = ptrdiff_t;
  215. using pointer = T*;
  216. using const_pointer = const T*;
  217. using reference = T&;
  218. using const_reference = const T&;
  219. using iterator = Iterator<false>;
  220. using const_iterator = Iterator<true>;
  221. using key_type = RedBlackKeyType<Comparator, value_type>;
  222. using const_key_pointer = const key_type*;
  223. using const_key_reference = const key_type&;
  224. template <bool Const>
  225. class Iterator {
  226. public:
  227. friend class IntrusiveRedBlackTree<T, Traits, Comparator>;
  228. using ImplIterator =
  229. std::conditional_t<Const, ImplType::const_iterator, ImplType::iterator>;
  230. using iterator_category = std::bidirectional_iterator_tag;
  231. using value_type = typename IntrusiveRedBlackTree::value_type;
  232. using difference_type = typename IntrusiveRedBlackTree::difference_type;
  233. using pointer = std::conditional_t<Const, IntrusiveRedBlackTree::const_pointer,
  234. IntrusiveRedBlackTree::pointer>;
  235. using reference = std::conditional_t<Const, IntrusiveRedBlackTree::const_reference,
  236. IntrusiveRedBlackTree::reference>;
  237. private:
  238. ImplIterator m_impl;
  239. private:
  240. constexpr explicit Iterator(ImplIterator it) : m_impl(it) {}
  241. constexpr explicit Iterator(typename ImplIterator::pointer p) : m_impl(p) {}
  242. constexpr ImplIterator GetImplIterator() const {
  243. return m_impl;
  244. }
  245. public:
  246. constexpr bool operator==(const Iterator& rhs) const {
  247. return m_impl == rhs.m_impl;
  248. }
  249. constexpr bool operator!=(const Iterator& rhs) const {
  250. return !(*this == rhs);
  251. }
  252. constexpr pointer operator->() const {
  253. return Traits::GetParent(std::addressof(*m_impl));
  254. }
  255. constexpr reference operator*() const {
  256. return *Traits::GetParent(std::addressof(*m_impl));
  257. }
  258. constexpr Iterator& operator++() {
  259. ++m_impl;
  260. return *this;
  261. }
  262. constexpr Iterator& operator--() {
  263. --m_impl;
  264. return *this;
  265. }
  266. constexpr Iterator operator++(int) {
  267. const Iterator it{*this};
  268. ++m_impl;
  269. return it;
  270. }
  271. constexpr Iterator operator--(int) {
  272. const Iterator it{*this};
  273. --m_impl;
  274. return it;
  275. }
  276. constexpr operator Iterator<true>() const {
  277. return Iterator<true>(m_impl);
  278. }
  279. };
  280. private:
  281. static constexpr int CompareImpl(const IntrusiveRedBlackTreeNode* lhs,
  282. const IntrusiveRedBlackTreeNode* rhs) {
  283. return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs));
  284. }
  285. static constexpr int CompareKeyImpl(const_key_reference key,
  286. const IntrusiveRedBlackTreeNode* rhs) {
  287. return Comparator::Compare(key, *Traits::GetParent(rhs));
  288. }
  289. // Define accessors using RB_* functions.
  290. constexpr IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) {
  291. return freebsd::RB_INSERT(m_impl.m_root, node, CompareImpl);
  292. }
  293. constexpr IntrusiveRedBlackTreeNode* FindImpl(IntrusiveRedBlackTreeNode const* node) const {
  294. return freebsd::RB_FIND(const_cast<ImplType::RootType&>(m_impl.m_root),
  295. const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
  296. }
  297. constexpr IntrusiveRedBlackTreeNode* NFindImpl(IntrusiveRedBlackTreeNode const* node) const {
  298. return freebsd::RB_NFIND(const_cast<ImplType::RootType&>(m_impl.m_root),
  299. const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
  300. }
  301. constexpr IntrusiveRedBlackTreeNode* FindKeyImpl(const_key_reference key) const {
  302. return freebsd::RB_FIND_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key,
  303. CompareKeyImpl);
  304. }
  305. constexpr IntrusiveRedBlackTreeNode* NFindKeyImpl(const_key_reference key) const {
  306. return freebsd::RB_NFIND_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key,
  307. CompareKeyImpl);
  308. }
  309. constexpr IntrusiveRedBlackTreeNode* FindExistingImpl(
  310. IntrusiveRedBlackTreeNode const* node) const {
  311. return freebsd::RB_FIND_EXISTING(const_cast<ImplType::RootType&>(m_impl.m_root),
  312. const_cast<IntrusiveRedBlackTreeNode*>(node), CompareImpl);
  313. }
  314. constexpr IntrusiveRedBlackTreeNode* FindExistingKeyImpl(const_key_reference key) const {
  315. return freebsd::RB_FIND_EXISTING_KEY(const_cast<ImplType::RootType&>(m_impl.m_root), key,
  316. CompareKeyImpl);
  317. }
  318. public:
  319. constexpr IntrusiveRedBlackTree() = default;
  320. // Iterator accessors.
  321. constexpr iterator begin() {
  322. return iterator(m_impl.begin());
  323. }
  324. constexpr const_iterator begin() const {
  325. return const_iterator(m_impl.begin());
  326. }
  327. constexpr iterator end() {
  328. return iterator(m_impl.end());
  329. }
  330. constexpr const_iterator end() const {
  331. return const_iterator(m_impl.end());
  332. }
  333. constexpr const_iterator cbegin() const {
  334. return this->begin();
  335. }
  336. constexpr const_iterator cend() const {
  337. return this->end();
  338. }
  339. constexpr iterator iterator_to(reference ref) {
  340. return iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
  341. }
  342. constexpr const_iterator iterator_to(const_reference ref) const {
  343. return const_iterator(m_impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
  344. }
  345. // Content management.
  346. constexpr bool empty() const {
  347. return m_impl.empty();
  348. }
  349. constexpr reference back() {
  350. return *Traits::GetParent(std::addressof(m_impl.back()));
  351. }
  352. constexpr const_reference back() const {
  353. return *Traits::GetParent(std::addressof(m_impl.back()));
  354. }
  355. constexpr reference front() {
  356. return *Traits::GetParent(std::addressof(m_impl.front()));
  357. }
  358. constexpr const_reference front() const {
  359. return *Traits::GetParent(std::addressof(m_impl.front()));
  360. }
  361. constexpr iterator erase(iterator it) {
  362. return iterator(m_impl.erase(it.GetImplIterator()));
  363. }
  364. constexpr iterator insert(reference ref) {
  365. ImplType::pointer node = Traits::GetNode(std::addressof(ref));
  366. this->InsertImpl(node);
  367. return iterator(node);
  368. }
  369. constexpr iterator find(const_reference ref) const {
  370. return iterator(this->FindImpl(Traits::GetNode(std::addressof(ref))));
  371. }
  372. constexpr iterator nfind(const_reference ref) const {
  373. return iterator(this->NFindImpl(Traits::GetNode(std::addressof(ref))));
  374. }
  375. constexpr iterator find_key(const_key_reference ref) const {
  376. return iterator(this->FindKeyImpl(ref));
  377. }
  378. constexpr iterator nfind_key(const_key_reference ref) const {
  379. return iterator(this->NFindKeyImpl(ref));
  380. }
  381. constexpr iterator find_existing(const_reference ref) const {
  382. return iterator(this->FindExistingImpl(Traits::GetNode(std::addressof(ref))));
  383. }
  384. constexpr iterator find_existing_key(const_key_reference ref) const {
  385. return iterator(this->FindExistingKeyImpl(ref));
  386. }
  387. };
  388. template <auto T, class Derived = Common::impl::GetParentType<T>>
  389. class IntrusiveRedBlackTreeMemberTraits;
  390. template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
  391. class IntrusiveRedBlackTreeMemberTraits<Member, Derived> {
  392. public:
  393. template <class Comparator>
  394. using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraits, Comparator>;
  395. using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
  396. private:
  397. template <class, class, class>
  398. friend class IntrusiveRedBlackTree;
  399. friend class impl::IntrusiveRedBlackTreeImpl;
  400. static constexpr IntrusiveRedBlackTreeNode* GetNode(Derived* parent) {
  401. return std::addressof(parent->*Member);
  402. }
  403. static constexpr IntrusiveRedBlackTreeNode const* GetNode(Derived const* parent) {
  404. return std::addressof(parent->*Member);
  405. }
  406. static Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
  407. return Common::GetParentPointer<Member, Derived>(node);
  408. }
  409. static Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) {
  410. return Common::GetParentPointer<Member, Derived>(node);
  411. }
  412. };
  413. template <auto T, class Derived = Common::impl::GetParentType<T>>
  414. class IntrusiveRedBlackTreeMemberTraitsDeferredAssert;
  415. template <class Parent, IntrusiveRedBlackTreeNode Parent::*Member, class Derived>
  416. class IntrusiveRedBlackTreeMemberTraitsDeferredAssert<Member, Derived> {
  417. public:
  418. template <class Comparator>
  419. using TreeType =
  420. IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeMemberTraitsDeferredAssert, Comparator>;
  421. using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
  422. private:
  423. template <class, class, class>
  424. friend class IntrusiveRedBlackTree;
  425. friend class impl::IntrusiveRedBlackTreeImpl;
  426. static constexpr IntrusiveRedBlackTreeNode* GetNode(Derived* parent) {
  427. return std::addressof(parent->*Member);
  428. }
  429. static constexpr IntrusiveRedBlackTreeNode const* GetNode(Derived const* parent) {
  430. return std::addressof(parent->*Member);
  431. }
  432. static Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
  433. return Common::GetParentPointer<Member, Derived>(node);
  434. }
  435. static Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) {
  436. return Common::GetParentPointer<Member, Derived>(node);
  437. }
  438. };
  439. template <class Derived>
  440. class alignas(void*) IntrusiveRedBlackTreeBaseNode : public IntrusiveRedBlackTreeNode {
  441. public:
  442. using IntrusiveRedBlackTreeNode::IntrusiveRedBlackTreeNode;
  443. constexpr Derived* GetPrev() {
  444. return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode*>(
  445. impl::IntrusiveRedBlackTreeImpl::GetPrev(this)));
  446. }
  447. constexpr const Derived* GetPrev() const {
  448. return static_cast<const Derived*>(static_cast<const IntrusiveRedBlackTreeBaseNode*>(
  449. impl::IntrusiveRedBlackTreeImpl::GetPrev(this)));
  450. }
  451. constexpr Derived* GetNext() {
  452. return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode*>(
  453. impl::IntrusiveRedBlackTreeImpl::GetNext(this)));
  454. }
  455. constexpr const Derived* GetNext() const {
  456. return static_cast<const Derived*>(static_cast<const IntrusiveRedBlackTreeBaseNode*>(
  457. impl::IntrusiveRedBlackTreeImpl::GetNext(this)));
  458. }
  459. };
  460. template <class Derived>
  461. class IntrusiveRedBlackTreeBaseTraits {
  462. public:
  463. template <class Comparator>
  464. using TreeType = IntrusiveRedBlackTree<Derived, IntrusiveRedBlackTreeBaseTraits, Comparator>;
  465. using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
  466. private:
  467. template <class, class, class>
  468. friend class IntrusiveRedBlackTree;
  469. friend class impl::IntrusiveRedBlackTreeImpl;
  470. static constexpr IntrusiveRedBlackTreeNode* GetNode(Derived* parent) {
  471. return static_cast<IntrusiveRedBlackTreeNode*>(
  472. static_cast<IntrusiveRedBlackTreeBaseNode<Derived>*>(parent));
  473. }
  474. static constexpr IntrusiveRedBlackTreeNode const* GetNode(Derived const* parent) {
  475. return static_cast<const IntrusiveRedBlackTreeNode*>(
  476. static_cast<const IntrusiveRedBlackTreeBaseNode<Derived>*>(parent));
  477. }
  478. static constexpr Derived* GetParent(IntrusiveRedBlackTreeNode* node) {
  479. return static_cast<Derived*>(static_cast<IntrusiveRedBlackTreeBaseNode<Derived>*>(node));
  480. }
  481. static constexpr Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) {
  482. return static_cast<const Derived*>(
  483. static_cast<const IntrusiveRedBlackTreeBaseNode<Derived>*>(node));
  484. }
  485. };
  486. } // namespace Common