From 58eb00c6936ac1a01663b2c363fb493a5e0c00a4 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 30 Jan 2015 12:54:28 +0100 Subject: [PATCH] src: add typesafe intrusive list This is a replacement for the QUEUE macros. It implements the same functionality but in a way that lets the compiler typecheck it. PR-URL: https://github.com/iojs/io.js/pull/667 Reviewed-By: Bert Belder Reviewed-By: Fedor Indutny Reviewed-By: Trevor Norris --- src/util-inl.h | 102 +++++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 63 ++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) diff --git a/src/util-inl.h b/src/util-inl.h index 6e962feffaf3e1..75bdb4784aaaf3 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -5,6 +5,108 @@ namespace node { +template +ListNode::ListNode() : prev_(this), next_(this) {} + +template +ListNode::~ListNode() { + Remove(); +} + +template +void ListNode::Remove() { + prev_->next_ = next_; + next_->prev_ = prev_; + prev_ = this; + next_ = this; +} + +template +bool ListNode::IsEmpty() const { + return prev_ == this; +} + +template +ListHead::Iterator::Iterator(ListNode* node) : node_(node) {} + +template +T* ListHead::Iterator::operator*() const { + return ContainerOf(M, node_); +} + +template +const typename ListHead::Iterator& +ListHead::Iterator::operator++() { + node_ = node_->next_; + return *this; +} + +template +bool ListHead::Iterator::operator!=(const Iterator& that) const { + return node_ != that.node_; +} + +template +ListHead::~ListHead() { + while (IsEmpty() == false) + head_.next_->Remove(); +} + +template +void ListHead::MoveBack(ListHead* that) { + if (IsEmpty()) + return; + ListNode* to = &that->head_; + head_.next_->prev_ = to->prev_; + to->prev_->next_ = head_.next_; + head_.prev_->next_ = to; + to->prev_ = head_.prev_; + head_.prev_ = &head_; + head_.next_ = &head_; +} + +template +void ListHead::PushBack(T* element) { + ListNode* that = &(element->*M); + head_.prev_->next_ = that; + that->prev_ = head_.prev_; + that->next_ = &head_; + head_.prev_ = that; +} + +template +void ListHead::PushFront(T* element) { + ListNode* that = &(element->*M); + head_.next_->prev_ = that; + that->prev_ = &head_; + that->next_ = head_.next_; + head_.next_ = that; +} + +template +bool ListHead::IsEmpty() const { + return head_.IsEmpty(); +} + +template +T* ListHead::PopFront() { + if (IsEmpty()) + return nullptr; + ListNode* node = head_.next_; + node->Remove(); + return ContainerOf(M, node); +} + +template +typename ListHead::Iterator ListHead::begin() const { + return Iterator(head_.next_); +} + +template +typename ListHead::Iterator ListHead::end() const { + return Iterator(const_cast*>(&head_)); +} + template ContainerOfHelper::ContainerOfHelper(Inner Outer::*field, Inner* pointer) diff --git a/src/util.h b/src/util.h index e0fa0fd0096bcc..5742252688111b 100644 --- a/src/util.h +++ b/src/util.h @@ -45,6 +45,69 @@ namespace node { #define UNREACHABLE() abort() +// TAILQ-style intrusive list node. +template +class ListNode; + +template +using ListNodeMember = ListNode T::*; + +// VS 2013 doesn't understand dependent templates. +#ifdef _MSC_VER +#define ListNodeMember(T) ListNodeMember +#else +#define ListNodeMember(T) ListNodeMember +#endif + +// TAILQ-style intrusive list head. +template +class ListHead; + +template +class ListNode { + public: + inline ListNode(); + inline ~ListNode(); + inline void Remove(); + inline bool IsEmpty() const; + + private: + template friend class ListHead; + ListNode* prev_; + ListNode* next_; + DISALLOW_COPY_AND_ASSIGN(ListNode); +}; + +template +class ListHead { + public: + class Iterator { + public: + inline T* operator*() const; + inline const Iterator& operator++(); + inline bool operator!=(const Iterator& that) const; + + private: + friend class ListHead; + inline explicit Iterator(ListNode* node); + ListNode* node_; + }; + + inline ListHead() = default; + inline ~ListHead(); + inline void MoveBack(ListHead* that); + inline void PushBack(T* element); + inline void PushFront(T* element); + inline bool IsEmpty() const; + inline T* PopFront(); + inline Iterator begin() const; + inline Iterator end() const; + + private: + ListNode head_; + DISALLOW_COPY_AND_ASSIGN(ListHead); +}; + // The helper is for doing safe downcasts from base types to derived types. template class ContainerOfHelper {