summaryrefslogtreecommitdiff
path: root/AK/IntrusiveList.h
diff options
context:
space:
mode:
authorAli Mohammad Pur <ali.mpfard@gmail.com>2021-04-20 13:01:27 +0430
committerLinus Groh <mail@linusgroh.de>2021-04-22 00:20:51 +0200
commit88b97f5367693dc6d83b35b2761a6069f1a4b720 (patch)
treee9f7f64980b5ccda744f032f1fbbca19a5b1b994 /AK/IntrusiveList.h
parent385714802813e2a0f9287922647966e654850ab5 (diff)
downloadserenity-88b97f5367693dc6d83b35b2761a6069f1a4b720.zip
AK: Make IntrusiveList work with NonnullRefPtr's
Diffstat (limited to 'AK/IntrusiveList.h')
-rw-r--r--AK/IntrusiveList.h39
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> {