diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2021-04-20 13:01:27 +0430 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-04-22 00:20:51 +0200 |
commit | 88b97f5367693dc6d83b35b2761a6069f1a4b720 (patch) | |
tree | e9f7f64980b5ccda744f032f1fbbca19a5b1b994 /AK/IntrusiveList.h | |
parent | 385714802813e2a0f9287922647966e654850ab5 (diff) | |
download | serenity-88b97f5367693dc6d83b35b2761a6069f1a4b720.zip |
AK: Make IntrusiveList work with NonnullRefPtr's
Diffstat (limited to 'AK/IntrusiveList.h')
-rw-r--r-- | AK/IntrusiveList.h | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/AK/IntrusiveList.h b/AK/IntrusiveList.h index 082a93ac3b..0282f5fad2 100644 --- a/AK/IntrusiveList.h +++ b/AK/IntrusiveList.h @@ -33,15 +33,32 @@ namespace AK { +namespace Detail { template<typename T, typename Container = RawPtr<T>> class IntrusiveListNode; template<typename T, typename Container> +struct SubstituteIntrusiveListNodeContainerType { + using Type = Container; +}; + +template<typename T> +struct SubstituteIntrusiveListNodeContainerType<T, NonnullRefPtr<T>> { + using Type = RefPtr<T>; +}; +} + +template<typename T, typename Container = RawPtr<T>> +using IntrusiveListNode = Detail::IntrusiveListNode<T, typename Detail::SubstituteIntrusiveListNodeContainerType<T, Container>::Type>; + +template<typename T, typename Container> class IntrusiveListStorage { private: - friend class IntrusiveListNode<T, Container>; + friend class Detail::IntrusiveListNode<T, Container>; + template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member> friend class IntrusiveList; + IntrusiveListNode<T, Container>* m_first { nullptr }; IntrusiveListNode<T, Container>* m_last { nullptr }; }; @@ -132,6 +149,8 @@ template<typename Contained> struct SelfReferenceIfNeeded<Contained, true> { }; +namespace Detail { + template<typename T, typename Container> class IntrusiveListNode { public: @@ -141,15 +160,22 @@ public: static constexpr bool IsRaw = IsPointer<Container>; + // Note: For some reason, clang does not consider `member` as declared here, and as declared above (`IntrusiveListNode<T, Container> T::*`) + // to be of equal types. so for now, just make the members public on clang. +#ifndef __clang__ private: template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member> - friend class IntrusiveList; + friend class ::AK::IntrusiveList; +#endif + IntrusiveListStorage<T, Container>* m_storage = nullptr; IntrusiveListNode<T, Container>* m_next = nullptr; IntrusiveListNode<T, Container>* m_prev = nullptr; SelfReferenceIfNeeded<Container, IsRaw> m_self; }; +} + template<class T, typename Container, IntrusiveListNode<T, Container> T::*member> inline typename IntrusiveList<T, Container, member>::Iterator& IntrusiveList<T, Container, member>::Iterator::erase() { @@ -309,6 +335,8 @@ inline T* IntrusiveList<T, Container, member>::node_to_value(IntrusiveListNode<T return bit_cast<T*>(bit_cast<unsigned char*>(&node) - bit_cast<unsigned char*>(member)); } +namespace Detail { + template<typename T, typename Container> inline IntrusiveListNode<T, Container>::~IntrusiveListNode() { @@ -341,12 +369,11 @@ inline bool IntrusiveListNode<T, Container>::is_in_list() const return m_storage != nullptr; } -// Specialise IntrusiveList(Node) for NonnullRefPtr +} + +// Specialise IntrusiveList for NonnullRefPtr // By default, intrusive lists cannot contain null entries anyway, so switch to RefPtr // and just make the user-facing functions deref the pointers. -template<typename T> -struct IntrusiveListNode<T, NonnullRefPtr<T>> : public IntrusiveListNode<T, RefPtr<T>> { -}; template<class T, IntrusiveListNode<T, NonnullRefPtr<T>> T::*member> class IntrusiveList<T, NonnullRefPtr<T>, member> : public IntrusiveList<T, RefPtr<T>, member> { |