mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 17:10:23 +00:00
AK: Make IntrusiveList work with NonnullRefPtr's
This commit is contained in:
parent
3857148028
commit
88b97f5367
Notes:
sideshowbarker
2024-07-18 19:15:23 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/88b97f53676 Pull-request: https://github.com/SerenityOS/serenity/pull/6543
1 changed files with 33 additions and 6 deletions
|
@ -33,15 +33,32 @@
|
||||||
|
|
||||||
namespace AK {
|
namespace AK {
|
||||||
|
|
||||||
|
namespace Detail {
|
||||||
template<typename T, typename Container = RawPtr<T>>
|
template<typename T, typename Container = RawPtr<T>>
|
||||||
class IntrusiveListNode;
|
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>
|
template<typename T, typename Container>
|
||||||
class IntrusiveListStorage {
|
class IntrusiveListStorage {
|
||||||
private:
|
private:
|
||||||
friend class IntrusiveListNode<T, Container>;
|
friend class Detail::IntrusiveListNode<T, Container>;
|
||||||
|
|
||||||
template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member>
|
template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member>
|
||||||
friend class IntrusiveList;
|
friend class IntrusiveList;
|
||||||
|
|
||||||
IntrusiveListNode<T, Container>* m_first { nullptr };
|
IntrusiveListNode<T, Container>* m_first { nullptr };
|
||||||
IntrusiveListNode<T, Container>* m_last { nullptr };
|
IntrusiveListNode<T, Container>* m_last { nullptr };
|
||||||
};
|
};
|
||||||
|
@ -132,6 +149,8 @@ template<typename Contained>
|
||||||
struct SelfReferenceIfNeeded<Contained, true> {
|
struct SelfReferenceIfNeeded<Contained, true> {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace Detail {
|
||||||
|
|
||||||
template<typename T, typename Container>
|
template<typename T, typename Container>
|
||||||
class IntrusiveListNode {
|
class IntrusiveListNode {
|
||||||
public:
|
public:
|
||||||
|
@ -141,15 +160,22 @@ public:
|
||||||
|
|
||||||
static constexpr bool IsRaw = IsPointer<Container>;
|
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:
|
private:
|
||||||
template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member>
|
template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member>
|
||||||
friend class IntrusiveList;
|
friend class ::AK::IntrusiveList;
|
||||||
|
#endif
|
||||||
|
|
||||||
IntrusiveListStorage<T, Container>* m_storage = nullptr;
|
IntrusiveListStorage<T, Container>* m_storage = nullptr;
|
||||||
IntrusiveListNode<T, Container>* m_next = nullptr;
|
IntrusiveListNode<T, Container>* m_next = nullptr;
|
||||||
IntrusiveListNode<T, Container>* m_prev = nullptr;
|
IntrusiveListNode<T, Container>* m_prev = nullptr;
|
||||||
SelfReferenceIfNeeded<Container, IsRaw> m_self;
|
SelfReferenceIfNeeded<Container, IsRaw> m_self;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
|
template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
|
||||||
inline typename IntrusiveList<T, Container, member>::Iterator& IntrusiveList<T, Container, member>::Iterator::erase()
|
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));
|
return bit_cast<T*>(bit_cast<unsigned char*>(&node) - bit_cast<unsigned char*>(member));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Detail {
|
||||||
|
|
||||||
template<typename T, typename Container>
|
template<typename T, typename Container>
|
||||||
inline IntrusiveListNode<T, Container>::~IntrusiveListNode()
|
inline IntrusiveListNode<T, Container>::~IntrusiveListNode()
|
||||||
{
|
{
|
||||||
|
@ -341,12 +369,11 @@ inline bool IntrusiveListNode<T, Container>::is_in_list() const
|
||||||
return m_storage != nullptr;
|
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
|
// By default, intrusive lists cannot contain null entries anyway, so switch to RefPtr
|
||||||
// and just make the user-facing functions deref the pointers.
|
// 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>
|
template<class T, IntrusiveListNode<T, NonnullRefPtr<T>> T::*member>
|
||||||
class IntrusiveList<T, NonnullRefPtr<T>, member> : public IntrusiveList<T, RefPtr<T>, member> {
|
class IntrusiveList<T, NonnullRefPtr<T>, member> : public IntrusiveList<T, RefPtr<T>, member> {
|
||||||
|
|
Loading…
Reference in a new issue