src: add typesafe intrusive list
authorBen Noordhuis <info@bnoordhuis.nl>
Fri, 30 Jan 2015 11:54:28 +0000 (12:54 +0100)
committerBen Noordhuis <info@bnoordhuis.nl>
Wed, 11 Feb 2015 22:06:29 +0000 (23:06 +0100)
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 <bertbelder@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
src/util-inl.h
src/util.h

index 6e962fe..75bdb47 100644 (file)
@@ -5,6 +5,108 @@
 
 namespace node {
 
+template <typename T>
+ListNode<T>::ListNode() : prev_(this), next_(this) {}
+
+template <typename T>
+ListNode<T>::~ListNode() {
+  Remove();
+}
+
+template <typename T>
+void ListNode<T>::Remove() {
+  prev_->next_ = next_;
+  next_->prev_ = prev_;
+  prev_ = this;
+  next_ = this;
+}
+
+template <typename T>
+bool ListNode<T>::IsEmpty() const {
+  return prev_ == this;
+}
+
+template <typename T, ListNodeMember(T) M>
+ListHead<T, M>::Iterator::Iterator(ListNode<T>* node) : node_(node) {}
+
+template <typename T, ListNodeMember(T) M>
+T* ListHead<T, M>::Iterator::operator*() const {
+  return ContainerOf(M, node_);
+}
+
+template <typename T, ListNodeMember(T) M>
+const typename ListHead<T, M>::Iterator&
+ListHead<T, M>::Iterator::operator++() {
+  node_ = node_->next_;
+  return *this;
+}
+
+template <typename T, ListNodeMember(T) M>
+bool ListHead<T, M>::Iterator::operator!=(const Iterator& that) const {
+  return node_ != that.node_;
+}
+
+template <typename T, ListNodeMember(T) M>
+ListHead<T, M>::~ListHead() {
+  while (IsEmpty() == false)
+    head_.next_->Remove();
+}
+
+template <typename T, ListNodeMember(T) M>
+void ListHead<T, M>::MoveBack(ListHead* that) {
+  if (IsEmpty())
+    return;
+  ListNode<T>* 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 <typename T, ListNodeMember(T) M>
+void ListHead<T, M>::PushBack(T* element) {
+  ListNode<T>* that = &(element->*M);
+  head_.prev_->next_ = that;
+  that->prev_ = head_.prev_;
+  that->next_ = &head_;
+  head_.prev_ = that;
+}
+
+template <typename T, ListNodeMember(T) M>
+void ListHead<T, M>::PushFront(T* element) {
+  ListNode<T>* that = &(element->*M);
+  head_.next_->prev_ = that;
+  that->prev_ = &head_;
+  that->next_ = head_.next_;
+  head_.next_ = that;
+}
+
+template <typename T, ListNodeMember(T) M>
+bool ListHead<T, M>::IsEmpty() const {
+  return head_.IsEmpty();
+}
+
+template <typename T, ListNodeMember(T) M>
+T* ListHead<T, M>::PopFront() {
+  if (IsEmpty())
+    return nullptr;
+  ListNode<T>* node = head_.next_;
+  node->Remove();
+  return ContainerOf(M, node);
+}
+
+template <typename T, ListNodeMember(T) M>
+typename ListHead<T, M>::Iterator ListHead<T, M>::begin() const {
+  return Iterator(head_.next_);
+}
+
+template <typename T, ListNodeMember(T) M>
+typename ListHead<T, M>::Iterator ListHead<T, M>::end() const {
+  return Iterator(const_cast<ListNode<T>*>(&head_));
+}
+
 template <typename Inner, typename Outer>
 ContainerOfHelper<Inner, Outer>::ContainerOfHelper(Inner Outer::*field,
                                                    Inner* pointer)
index e0fa0fd..5742252 100644 (file)
@@ -45,6 +45,69 @@ namespace node {
 
 #define UNREACHABLE() abort()
 
+// TAILQ-style intrusive list node.
+template <typename T>
+class ListNode;
+
+template <typename T>
+using ListNodeMember = ListNode<T> T::*;
+
+// VS 2013 doesn't understand dependent templates.
+#ifdef _MSC_VER
+#define ListNodeMember(T) ListNodeMember
+#else
+#define ListNodeMember(T) ListNodeMember<T>
+#endif
+
+// TAILQ-style intrusive list head.
+template <typename T, ListNodeMember(T) M>
+class ListHead;
+
+template <typename T>
+class ListNode {
+ public:
+  inline ListNode();
+  inline ~ListNode();
+  inline void Remove();
+  inline bool IsEmpty() const;
+
+ private:
+  template <typename U, ListNodeMember(U) M> friend class ListHead;
+  ListNode* prev_;
+  ListNode* next_;
+  DISALLOW_COPY_AND_ASSIGN(ListNode);
+};
+
+template <typename T, ListNodeMember(T) M>
+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<T>* node);
+    ListNode<T>* 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<T> head_;
+  DISALLOW_COPY_AND_ASSIGN(ListHead);
+};
+
 // The helper is for doing safe downcasts from base types to derived types.
 template <typename Inner, typename Outer>
 class ContainerOfHelper {