intrusive_red_black_tree.h 19 KB

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