intrusive_red_black_tree.h 19 KB

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