util/IntrusiveList: add hook class SafeLinkIntrusiveListHook

Similar to boost::intrusive::safe_link.
This commit is contained in:
Max Kellermann 2021-02-24 20:28:47 +01:00
parent 8fe8f09027
commit 1048f23680

View File

@ -65,21 +65,15 @@ private:
};
/**
* A variant of #IntrusiveListHook which auto-unlinks itself from the
* list upon destruction. As a side effect, it has an is_linked()
* method.
* A variant of #IntrusiveListHook which keeps track of whether it is
* currently in a list.
*/
class AutoUnlinkIntrusiveListHook : public IntrusiveListHook {
class SafeLinkIntrusiveListHook : public IntrusiveListHook {
public:
AutoUnlinkIntrusiveListHook() noexcept {
SafeLinkIntrusiveListHook() noexcept {
siblings.next = nullptr;
}
~AutoUnlinkIntrusiveListHook() noexcept {
if (is_linked())
unlink();
}
void unlink() noexcept {
IntrusiveListHook::unlink();
siblings.next = nullptr;
@ -90,6 +84,19 @@ public:
}
};
/**
* A variant of #IntrusiveListHook which auto-unlinks itself from the
* list upon destruction. As a side effect, it has an is_linked()
* method.
*/
class AutoUnlinkIntrusiveListHook : public SafeLinkIntrusiveListHook {
public:
~AutoUnlinkIntrusiveListHook() noexcept {
if (is_linked())
unlink();
}
};
template<typename T>
class IntrusiveList {
IntrusiveListNode head{&head, &head};
@ -140,7 +147,7 @@ public:
}
~IntrusiveList() noexcept {
if constexpr (std::is_base_of<AutoUnlinkIntrusiveListHook, T>::value)
if constexpr (std::is_base_of<SafeLinkIntrusiveListHook, T>::value)
clear();
}
@ -151,8 +158,8 @@ public:
}
void clear() noexcept {
if constexpr (std::is_base_of<AutoUnlinkIntrusiveListHook, T>::value) {
/* for AutoUnlinkIntrusiveListHook, we need to
if constexpr (std::is_base_of<SafeLinkIntrusiveListHook, T>::value) {
/* for SafeLinkIntrusiveListHook, we need to
remove each item manually, or else its
is_linked() method will not work */
while (!empty())