diff --git a/src/util/dlist.h b/src/util/dlist.h index 4c0e51e58..584817785 100644 --- a/src/util/dlist.h +++ b/src/util/dlist.h @@ -155,15 +155,25 @@ public: elem->init(elem); } - bool invariant() const { - auto* e = this; - do { - if (e->m_next->m_prev != e) - return false; - e = e->m_next; - } - while (e != this); - return true; + bool invariant() const { + auto* e = this; + const T* slow = static_cast(this); + const T* fast = m_next; + bool looped = false; + // m_next of each node should point back to m_prev of the following node, + // and m_prev of each node should point forward to m_next of the preceding node. + while (slow != fast) { + if (fast->m_prev->m_next != fast || fast->m_next->m_prev != fast) { + return false; + } + fast = fast->m_next; + looped = looped || (fast == static_cast(this)); + if (!looped && fast == m_next) { + // We should be able to traverse back to the starting node. + return false; + } + } + return true; } static bool contains(T const* list, T const* elem) { @@ -245,4 +255,4 @@ template < typename T dll_iterator end(T const& list) { return dll_iterator::mk_end(&list); -} +} \ No newline at end of file