42#define IL_NEW() NEW(IntrusiveList)
44#define IL_EMPTY(this) (this.il_head == NULL)
46#define IL_FIRST(this) (this.il_head)
47#define IL_LAST(this) (this.il_tail)
48#define IL_PEEK(this) (this.il_tail)
53 assert(
this,
return false);
54 return it.(this.il_nextfld) || this.il_head == it || this.il_tail == it;
65 .entity il_next = this.il_nextfld;
66 .entity il_prev = this.il_prevfld;
69 entity tail = it.(il_prev) = this.il_tail;
70 tail ? (tail.(il_next) = it) : this.il_head = it;
84 .entity il_next = this.il_nextfld;
85 .entity il_prev = this.il_prevfld;
88 entity head = it.(il_next) = this.il_head;
89 head ? (head.(il_prev) = it) : this.il_tail = it;
102 .entity il_next = this.il_nextfld;
103 .entity il_prev = this.il_prevfld;
105 if (!this.il_tail)
return NULL;
109 else this.il_head = this.il_tail =
NULL;
110 if (this.il_loop_item == it)
111 this.il_loop_item =
NULL;
123 .entity il_next = this.il_nextfld;
124 .entity il_prev = this.il_prevfld;
126 if (!this.il_head)
return NULL;
130 else this.il_head = this.il_tail =
NULL;
131 if (this.il_loop_item == it)
132 this.il_loop_item = it.(il_next);
144 .entity il_next = this.il_nextfld;
145 .entity il_prev = this.il_prevfld;
149 entity ohead = this.il_head;
150 entity otail = this.il_tail;
153 LOG_DEBUGF(
"remove %i (%i :: %i), head: %i -> %i, tail: %i -> %i", it, it.(il_prev), it.(il_next), ohead,
this.il_head, otail,
this.il_tail);
154 if (this.il_loop_item == it)
155 this.il_loop_item = it.(il_next);
156 it.(il_next) = it.(il_prev) =
NULL;
162#define IL_CLEAR(this) \
164 IntrusiveList _il = this; \
166 .entity il_prev = _il.il_prevfld; \
167 .entity il_next = _il.il_nextfld; \
169 for (entity _next, _it = _il.il_head; _it; (_it = _next, ++i)) \
171 _next = _it.(il_next); \
172 _it.(il_next) = _it.(il_prev) = NULL; \
174 _il.il_head = _il.il_tail = NULL; \
180#define IL_DELETE(this) \
186#define IL_EACH(this, cond, body) \
188 IntrusiveList _il = this; \
190 .entity il_next = _il.il_nextfld; \
192 entity il_loop_item_save = this.il_loop_item; \
193 this.il_loop_item = NULL; \
194 for (entity _next, _it = _il.il_head; _it; (_it = _next, ++i)) \
196 const noref entity it = _it; \
197 this.il_loop_item = it; \
198 _next = it.(il_next); \
199 if (cond) { LAMBDA(body) } \
200 if (this.il_loop_item != it) \
201 _next = this.il_loop_item; \
203 _next = it.(il_next); \
205 this.il_loop_item = il_loop_item_save; \
213#define IL_FLOOR(n) ((n) | 0)
214#define IL_CEIL(n) IL_FLOOR((n) + 0.5)
216#define IL_LISTS_PER_BIT IL_CEIL(IL_MAX / (3 * 24))
221 .entity nextfld, prevfld;
228 int flds_idx =
id * 2;
233 if (bit < (1 * 24)) this.
il_listmask =
'1 0 0' *
BIT(bit - (0 * 24));
234 else if (bit < (2 * 24)) this.
il_listmask =
'0 1 0' *
BIT(bit - (1 * 24));
235 else if (bit < (3 * 24)) this.
il_listmask =
'0 0 1' *
BIT(bit - (2 * 24));
239 this.il_nextfld = nextfld;
240 this.il_prevfld = prevfld;
259 for (
int i = 0; i <
IL_MAX; ++i) {
280 it.il_lists =
'0 0 0';
281 for (
int i = 0; i <
IL_MAX * 2; ++i)
282 it.il_links_flds[i] = nil;
293 for (
int i = 0; i <
IL_MAX; ++i) {
295 if ((lists & list.il_listmask) &&
IL_CONTAINS(list,
this)) {
303#define IL_TEST_BUILD() s = il_test_build(il_test, ent1, ent2, ent3, ent4, ent5)
316TEST(intrusivelist, ModificationsWhileLooping)
319 entity ent1 =
new(1), ent2 =
new(2), ent3 =
new(3), ent4 =
new(4), ent5 =
new(5);
325 s =
strcat(s, it.classname);
326 if (it == ent2)
IL_REMOVE(il_test, ent3);
327 if (it == ent4)
IL_PUSH(il_test, ent3);
334 s =
strcat(s, it.classname);
335 if (it == ent2)
IL_REMOVE(il_test, ent2);
336 if (it == ent3)
IL_REMOVE(il_test, ent3);
337 if (it == ent3)
IL_REMOVE(il_test, ent4);
338 if (it == ent5)
IL_POP(il_test);
346 s =
strcat(s, it.classname);
348 if (it == ent4)
IL_POP(il_test);
355 s =
strcat(s, it.classname);
359 s =
strcat(s, it.classname);
363 s =
strcat(s, it.classname);
372 delete(ent1);
delete(ent2);
delete(ent3);
delete(ent4);
delete(ent5);
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
limitations: NULL cannot be present elements can only be present once a maximum of IL_MAX lists can e...
ATTRIB(IntrusiveList, il_head, entity)
ERASEABLE void IL_DTOR(entity this)
ERASEABLE void IL_REMOVE(IntrusiveList this, entity it)
Remove any element, anywhere in the list.
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
ERASEABLE bool IL_CONTAINS(IntrusiveList this, entity it)
ERASEABLE void IL_ENDFRAME()
void IL_REMOVE_RAW(entity it)
ERASEABLE entity IL_POP(IntrusiveList this)
Pop from tail.
ERASEABLE void IL_INIT(entity this)
const int IL_MAX
Maximum amount of creatable lists.
#define IL_EACH(this, cond, body)
ERASEABLE entity IL_SHIFT(IntrusiveList this)
Pop from head.
entity il_links_flds[IL_MAX *2]
#define IL_CLEAR(this)
Remove all elements.
IntrusiveList il_links[IL_MAX]
void ONREMOVE(entity this)
#define IL_DELETE(this)
Delete the list.
ERASEABLE entity IL_UNSHIFT(IntrusiveList this, entity it)
Push to head.
string il_test_build(entity il_test, entity ent1, entity ent2, entity ent3, entity ent4, entity ent5)
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define DESTRUCTOR(cname)
#define TEST(suite, test)
Use UpperCamelCase for suite and test only.
#define SUCCEED()
Must be present at the end of a test.
#define EXPECT_TRUE(condition)