Cogs.Core
IntrusiveList.cpp
1#include <cstdlib>
2#include <cassert>
3#include "IntrusiveList.h"
4
5namespace {
6
7
8 size_t count(Cogs::IntrusiveList* list)
9 {
10
11 size_t n = 0;
12 for(auto * item : *list) {
13 (void)item;
14// for (auto item = list->head; item != (Cogs::IntrusiveNode*)&list->tail; item = item->next) {
15 n++;
16 }
17 return n;
18 }
19
20}
21
22
23Cogs::IntrusiveList::IntrusiveList()
24{
25 head = (IntrusiveNode*)&tail;
26 tail = nullptr;
27 tailPrev = (IntrusiveNode*)&head;
28
29 assert(count(this) == 0);
30}
31
32bool Cogs::IntrusiveList::empty() const
33{
34 return tailPrev == (IntrusiveNode*)&head;
35}
36
37void Cogs::IntrusiveList::pushFront(IntrusiveNode* node)
38{
39 assert(node->next == nullptr);
40 assert(node->prev == nullptr);
41
42 auto n = count(this);
43
44 node->next = head;
45 node->prev = (IntrusiveNode*)&head;
46 head->prev = node;
47 head = node;
48
49 auto m = count(this);
50 assert(n + 1 == m);
51
52 assert(head->prev != nullptr);
53 assert(tailPrev != (IntrusiveNode*)&head);
54}
55
56void Cogs::IntrusiveList::pushBack(IntrusiveNode* node)
57{
58 assert(node->next == nullptr);
59 assert(node->prev == nullptr);
60
61 auto n = count(this);
62
63 node->next = (IntrusiveNode*)&tail;
64 node->prev = tailPrev;
65 tailPrev->next = node;
66 tailPrev = node;
67
68 auto m = count(this);
69 assert(n + 1 == m);
70
71 assert(head->prev != nullptr);
72 assert(tailPrev != (IntrusiveNode*)&head);
73}
74
75void Cogs::IntrusiveList::insert(IntrusiveNode* prev, IntrusiveNode* node)
76{
77 assert(prev->next);
78 assert(prev->prev);
79 assert(node->next == nullptr);
80 assert(node->prev == nullptr);
81 assert(head->prev != nullptr && "List is empty");
82 assert(tailPrev != (IntrusiveNode*)&head && "List is empty");
83
84 auto n = count(this);
85
86 if (prev->next) {
87 node->next = prev->next;
88 node->prev = prev;
89 prev->next->prev = node;
90 prev->next = node;
91 }
92 else { // tail node
93 node->next = (IntrusiveNode*)&tail;
94 node->prev = tailPrev;
95 tailPrev->next = node;
96 tailPrev = node;
97 }
98
99 auto m = count(this);
100 assert(n + 1 == m);
101
102 assert(head->prev != nullptr);
103 assert(tailPrev != (IntrusiveNode*)&head);
104}
105
106Cogs::IntrusiveNode* Cogs::IntrusiveList::popFront()
107{
108 IntrusiveNode* node = head->next;
109 if (node) {
110
111 auto n = count(this);
112
113 node->prev = (IntrusiveNode*)&head;
114 node = head;
115 head = node->next;
116
117 node->next = nullptr;
118 node->prev = nullptr;
119
120 auto m = count(this);
121 assert(n == m + 1);
122 }
123 return node;
124}
125
126Cogs::IntrusiveNode* Cogs::IntrusiveList::back()
127{
128 if (tailPrev != (IntrusiveNode*)&head) {
129 return tailPrev;
130 }
131 else {
132 return nullptr;
133 }
134}
135
136void Cogs::IntrusiveList::remove(IntrusiveNode* node)
137{
138 assert(node);
139
140 auto n = count(this);
141
142 node->prev->next = node->next;
143 node->next->prev = node->prev;
144 node->next = nullptr;
145 node->prev = nullptr;
146
147 auto m = count(this);
148 assert(n == m + 1);
149}
150
151Cogs::IntrusiveNode* Cogs::IntrusiveList::IntrusiveList::popBack()
152{
153 IntrusiveNode* node = back();
154 if (node) {
155 remove(node);
156 }
157 return node;
158}