48#define IL_NEW() NEW(IntrusiveList)
50#define IL_EMPTY(this) (this.il_head == NULL)
52#define IL_FIRST(this) (this.il_head)
53#define IL_LAST(this) (this.il_tail)
54#define IL_PEEK(this) (this.il_tail)
59 assert(
this,
return false);
60 return (it.(this.il_nextfld) ||
this.il_head == it ||
this.il_tail == it);
69 .entity il_next = this.il_nextfld;
70 .entity il_prev = this.il_prevfld;
73 entity tail = it.(il_prev) = this.il_tail;
89 .entity il_next = this.il_nextfld;
90 .entity il_prev = this.il_prevfld;
93 entity head = it.(il_next) = this.il_head;
108 .entity il_next = this.il_nextfld;
109 .entity il_prev = this.il_prevfld;
116 (this.il_tail =
prev).(il_next) =
NULL;
118 this.il_head = this.il_tail =
NULL;
119 if (this.il_loop_item == it)
120 this.il_loop_item =
NULL;
130 .entity il_next = this.il_nextfld;
131 .entity il_prev = this.il_prevfld;
138 (this.il_head =
next).(il_prev) =
NULL;
140 this.il_head = this.il_tail =
NULL;
141 if (this.il_loop_item == it)
142 this.il_loop_item = it.(il_next);
152 .entity il_next = this.il_nextfld;
153 .entity il_prev = this.il_prevfld;
157 entity ohead = this.il_head;
158 entity otail = this.il_tail;
167 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);
168 if (this.il_loop_item == it)
169 this.il_loop_item = it.(il_next);
170 it.(il_next) = it.(il_prev) =
NULL;
174#define IL_CLEAR(this) MACRO_BEGIN \
175 IntrusiveList _il = this; \
177 .entity il_prev = _il.il_prevfld; \
178 .entity il_next = _il.il_nextfld; \
180 for (entity _next, _it = _il.il_head; _it; (_it = _next, ++i)) \
182 _next = _it.(il_next); \
183 _it.(il_next) = _it.(il_prev) = NULL; \
185 _il.il_head = _il.il_tail = NULL; \
189#define IL_DELETE(this) MACRO_BEGIN \
194#define IL_EACH(this, cond, body) MACRO_BEGIN \
195 IntrusiveList _il = this; \
197 .entity il_next = _il.il_nextfld; \
199 entity il_loop_item_save = this.il_loop_item; \
200 this.il_loop_item = NULL; \
201 for (entity _next, _it = _il.il_head; _it; _it = _next, ++i) \
203 const noref entity it = _it; \
204 this.il_loop_item = it; \
205 _next = it.(il_next); \
208 if (this.il_loop_item != it) \
209 _next = this.il_loop_item; \
211 _next = it.(il_next); \
213 this.il_loop_item = il_loop_item_save; \
221#define IL_FLOOR(n) ((n) | 0)
222#define IL_CEIL(n) IL_FLOOR((n) + 0.5)
224#define IL_LISTS_PER_BIT IL_CEIL(IL_MAX / (3 * 24))
229 .entity nextfld, prevfld;
239 int flds_idx =
id * 2;
246 else if (bit < 2 * 24)
248 else if (bit < 3 * 24)
255 this.il_nextfld = nextfld;
256 this.il_prevfld = prevfld;
275 for (
int i = 0; i <
IL_MAX; ++i)
298 it.il_lists =
'0 0 0';
299 for (
int i = 0; i <
IL_MAX * 2; ++i)
300 it.il_links_flds[i] = nil;
311 for (
int i = 0; i <
IL_MAX; ++i)
314 if ((lists & list.il_listmask) &&
IL_CONTAINS(list,
this))
320#define IL_TEST_BUILD() s = il_test_build(il_test, ent1, ent2, ent3, ent4, ent5)
333TEST(intrusivelist, ModificationsWhileLooping)
336 entity ent1 =
new(1), ent2 =
new(2), ent3 =
new(3), ent4 =
new(4), ent5 =
new(5);
342 s =
strcat(s, it.classname);
343 if (it == ent2)
IL_REMOVE(il_test, ent3);
344 if (it == ent4)
IL_PUSH(il_test, ent3);
351 s =
strcat(s, it.classname);
352 if (it == ent2)
IL_REMOVE(il_test, ent2);
353 if (it == ent3)
IL_REMOVE(il_test, ent3);
354 if (it == ent3)
IL_REMOVE(il_test, ent4);
355 if (it == ent5)
IL_POP(il_test);
363 s =
strcat(s, it.classname);
365 if (it == ent4)
IL_POP(il_test);
372 s =
strcat(s, it.classname);
376 s =
strcat(s, it.classname);
386 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)
Clears any IL data from an entity (not an intrusive list).
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)
Called when an entity is deleted with delete() / remove() or when a player disconnects.
#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)