Skip to content

Commit 58eb00c

Browse files
committed
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: #667 Reviewed-By: Bert Belder <[email protected]> Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Trevor Norris <[email protected]>
1 parent 7061669 commit 58eb00c

File tree

2 files changed

+165
-0
lines changed

2 files changed

+165
-0
lines changed

src/util-inl.h

+102
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,108 @@
55

66
namespace node {
77

8+
template <typename T>
9+
ListNode<T>::ListNode() : prev_(this), next_(this) {}
10+
11+
template <typename T>
12+
ListNode<T>::~ListNode() {
13+
Remove();
14+
}
15+
16+
template <typename T>
17+
void ListNode<T>::Remove() {
18+
prev_->next_ = next_;
19+
next_->prev_ = prev_;
20+
prev_ = this;
21+
next_ = this;
22+
}
23+
24+
template <typename T>
25+
bool ListNode<T>::IsEmpty() const {
26+
return prev_ == this;
27+
}
28+
29+
template <typename T, ListNodeMember(T) M>
30+
ListHead<T, M>::Iterator::Iterator(ListNode<T>* node) : node_(node) {}
31+
32+
template <typename T, ListNodeMember(T) M>
33+
T* ListHead<T, M>::Iterator::operator*() const {
34+
return ContainerOf(M, node_);
35+
}
36+
37+
template <typename T, ListNodeMember(T) M>
38+
const typename ListHead<T, M>::Iterator&
39+
ListHead<T, M>::Iterator::operator++() {
40+
node_ = node_->next_;
41+
return *this;
42+
}
43+
44+
template <typename T, ListNodeMember(T) M>
45+
bool ListHead<T, M>::Iterator::operator!=(const Iterator& that) const {
46+
return node_ != that.node_;
47+
}
48+
49+
template <typename T, ListNodeMember(T) M>
50+
ListHead<T, M>::~ListHead() {
51+
while (IsEmpty() == false)
52+
head_.next_->Remove();
53+
}
54+
55+
template <typename T, ListNodeMember(T) M>
56+
void ListHead<T, M>::MoveBack(ListHead* that) {
57+
if (IsEmpty())
58+
return;
59+
ListNode<T>* to = &that->head_;
60+
head_.next_->prev_ = to->prev_;
61+
to->prev_->next_ = head_.next_;
62+
head_.prev_->next_ = to;
63+
to->prev_ = head_.prev_;
64+
head_.prev_ = &head_;
65+
head_.next_ = &head_;
66+
}
67+
68+
template <typename T, ListNodeMember(T) M>
69+
void ListHead<T, M>::PushBack(T* element) {
70+
ListNode<T>* that = &(element->*M);
71+
head_.prev_->next_ = that;
72+
that->prev_ = head_.prev_;
73+
that->next_ = &head_;
74+
head_.prev_ = that;
75+
}
76+
77+
template <typename T, ListNodeMember(T) M>
78+
void ListHead<T, M>::PushFront(T* element) {
79+
ListNode<T>* that = &(element->*M);
80+
head_.next_->prev_ = that;
81+
that->prev_ = &head_;
82+
that->next_ = head_.next_;
83+
head_.next_ = that;
84+
}
85+
86+
template <typename T, ListNodeMember(T) M>
87+
bool ListHead<T, M>::IsEmpty() const {
88+
return head_.IsEmpty();
89+
}
90+
91+
template <typename T, ListNodeMember(T) M>
92+
T* ListHead<T, M>::PopFront() {
93+
if (IsEmpty())
94+
return nullptr;
95+
ListNode<T>* node = head_.next_;
96+
node->Remove();
97+
return ContainerOf(M, node);
98+
}
99+
100+
template <typename T, ListNodeMember(T) M>
101+
typename ListHead<T, M>::Iterator ListHead<T, M>::begin() const {
102+
return Iterator(head_.next_);
103+
}
104+
105+
template <typename T, ListNodeMember(T) M>
106+
typename ListHead<T, M>::Iterator ListHead<T, M>::end() const {
107+
return Iterator(const_cast<ListNode<T>*>(&head_));
108+
}
109+
8110
template <typename Inner, typename Outer>
9111
ContainerOfHelper<Inner, Outer>::ContainerOfHelper(Inner Outer::*field,
10112
Inner* pointer)

src/util.h

+63
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,69 @@ namespace node {
4545

4646
#define UNREACHABLE() abort()
4747

48+
// TAILQ-style intrusive list node.
49+
template <typename T>
50+
class ListNode;
51+
52+
template <typename T>
53+
using ListNodeMember = ListNode<T> T::*;
54+
55+
// VS 2013 doesn't understand dependent templates.
56+
#ifdef _MSC_VER
57+
#define ListNodeMember(T) ListNodeMember
58+
#else
59+
#define ListNodeMember(T) ListNodeMember<T>
60+
#endif
61+
62+
// TAILQ-style intrusive list head.
63+
template <typename T, ListNodeMember(T) M>
64+
class ListHead;
65+
66+
template <typename T>
67+
class ListNode {
68+
public:
69+
inline ListNode();
70+
inline ~ListNode();
71+
inline void Remove();
72+
inline bool IsEmpty() const;
73+
74+
private:
75+
template <typename U, ListNodeMember(U) M> friend class ListHead;
76+
ListNode* prev_;
77+
ListNode* next_;
78+
DISALLOW_COPY_AND_ASSIGN(ListNode);
79+
};
80+
81+
template <typename T, ListNodeMember(T) M>
82+
class ListHead {
83+
public:
84+
class Iterator {
85+
public:
86+
inline T* operator*() const;
87+
inline const Iterator& operator++();
88+
inline bool operator!=(const Iterator& that) const;
89+
90+
private:
91+
friend class ListHead;
92+
inline explicit Iterator(ListNode<T>* node);
93+
ListNode<T>* node_;
94+
};
95+
96+
inline ListHead() = default;
97+
inline ~ListHead();
98+
inline void MoveBack(ListHead* that);
99+
inline void PushBack(T* element);
100+
inline void PushFront(T* element);
101+
inline bool IsEmpty() const;
102+
inline T* PopFront();
103+
inline Iterator begin() const;
104+
inline Iterator end() const;
105+
106+
private:
107+
ListNode<T> head_;
108+
DISALLOW_COPY_AND_ASSIGN(ListHead);
109+
};
110+
48111
// The helper is for doing safe downcasts from base types to derived types.
49112
template <typename Inner, typename Outer>
50113
class ContainerOfHelper {

0 commit comments

Comments
 (0)