BRL-CAD
list.h
Go to the documentation of this file.
1/* L I S T . H
2 * BRL-CAD
3 *
4 * Copyright (c) 2004-2023 United States Government as represented by
5 * the U.S. Army Research Laboratory.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * version 2.1 as published by the Free Software Foundation.
10 *
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this file; see the file named COPYING for more
18 * information.
19 */
20
21#ifndef BU_LIST_H
22#define BU_LIST_H
23
24#include "common.h"
25
26#include "bu/defines.h"
27#include "bu/assert.h"
28#include "bu/magic.h"
29
30__BEGIN_DECLS
31
32/* TODO: Plan for replacement of bu_list with a more memory coherent
33 * vector/array storage, ideally lockfree and threadsafe but not
34 * strictly necessary. Some options to consider and benchmark:
35 *
36 * http://libcds.sourceforge.net
37 * https://code.google.com/archive/p/ccl/
38 * http://sglib.sourceforge.net
39 * tbb::concurrent_vector
40 * std::vector et. al
41 * https://github.com/xant/libhl
42 */
43
44/*----------------------------------------------------------------------*/
45/** @addtogroup bu_list
46 *
47 * @brief Support routines for doubly-linked lists.
48 *
49 * These macros assume that all user-provided structures will have a
50 * "struct bu_list" as their first element (often named "l" [ell]).
51 * Thus, a pointer to the bu_list struct is a "pun" for the
52 * user-provided structure as well, and the pointers can be converted
53 * back and forth safely with type casts.
54 *
55 * Furthermore, the head of the linked list could be a full instance
56 * of the user-provided structure (although the storage-conscious
57 * programmer could make the head just an bu_list structure, with
58 * careful type casting). This results in a doubly-linked circular
59 * list, with the head having the same shape as all the list members.
60 * The application is free to make use of this symmetry and store data
61 * values in the head, or the extra storage in the head can be
62 * ignored.
63 *
64 * Where a macro expects an argument "p", it should be a pointer to a
65 * user-provided structure.
66 *
67 * Where a macro expects an argument "headp", it should be a pointer
68 * to a "struct bu_list" located in the list head, e.g., &(head.l).
69 *
70 * Where a macro expects an argument "old", "new", or "cur", it should
71 * be a pointer to the "struct bu_list" located either in a
72 * user-provided structure, e.g. &((p)->l), or for the case of "old"
73 * it may also be in the list head.
74 *
75 @code
76 --- BEGIN EXAMPLE ---
77
78 // make bu_list the first element in your structure
79 struct my_structure {
80 struct bu_list l;
81 int my_data;
82 };
83
84 // your actual list
85 struct my_structure *my_list = NULL;
86
87 // allocate and initialize your list head
88 BU_GET(my_list, struct my_structure);
89 BU_LIST_INIT(&(my_list->l));
90 my_list->my_data = -1;
91
92 // add a new element to your list
93 struct my_structure *new_entry;
94 BU_GET(new_entry, struct my_structure);
95 new_entry->my_data = rand();
96 BU_LIST_PUSH(&(my_list->l), &(new_entry->l));
97
98 // iterate over your list, remove all items
99 struct my_structure *entry;
100 while (BU_LIST_WHILE(entry, my_structure, &(my_list->l))) {
101 bu_log("Entry value is %d\n", entry->my_data);
102 BU_LIST_DEQUEUE(&(entry->l));
103 BU_PUT(entry, struct my_structure);
104 }
105 BU_PUT(my_list, struct my_structure);
106
107 --- END EXAMPLE ---
108 @endcode
109 *
110 * Dequeueing the head of a list is a valid and well defined operation
111 * which should be performed with caution. Unless a pointer to some
112 * other element of the list is retained by the application, the rest
113 * of the linked list can no longer be referred to.
114 *
115 * The "magic" field of the list header _must_ be set to the constant
116 * BU_LIST_HEAD_MAGIC, but the "magic" field of all list members
117 * should be established by user code, to identify the type of
118 * structure that the bu_list structure is embedded in. It is
119 * permissible for one list to contain an arbitrarily mixed set of
120 * user "magic" numbers, as long as the head is properly marked.
121 *
122 * There is a dual set of terminology used in some of the macros:
123 *
124 * FIRST/ LAST - from the point of view of the list head
125 * NEXT / PREV - from the point of view of a list member
126 * forw / back - the actual pointer names
127 */
128/** @{*/
129/** @file bu/list.h */
130
131struct bu_list {
132 uint32_t magic; /**< @brief Magic # for mem id/check */
133 struct bu_list *forw; /**< @brief "forward", "next" */
134 struct bu_list *back; /**< @brief "back", "last" */
135};
136typedef struct bu_list bu_list_t;
137#define BU_LIST_NULL ((struct bu_list *)0)
138
139/**
140 * macro for setting the magic number of a non-head list node
141 */
142#define BU_LIST_MAGIC_SET(_l, _magic) {(_l)->magic = (_magic);}
143
144/**
145 * macro for testing whether a list node's magic number is equal to a
146 * specific magic number
147 */
148#define BU_LIST_MAGIC_EQUAL(_l, _magic) ((_l)->magic == (_magic))
149
150/**
151 * there is no reliable way to assert the integrity of an arbitrary
152 * bu_list struct since the magic can be anything, therefore there is
153 * no BU_CK_LIST(). we can, however, check for a valid head node.
154 */
155#define BU_CK_LIST_HEAD(_p) BU_CKMAG((_p), BU_LIST_HEAD_MAGIC, "bu_list")
156
157/**
158 * initializes a bu_list struct as a circular list without allocating
159 * any memory. call BU_LIST_MAGIC_SET() to change the list type.
160 */
161#define BU_LIST_INIT(_headp) { \
162 BU_ASSERT((void *)(_headp) != (void *)NULL); \
163 (_headp)->forw = (_headp)->back = (_headp); \
164 (_headp)->magic = BU_LIST_HEAD_MAGIC; /* used by circ. macros */ }
165
166/**
167 * initializes a bu_list struct node with a particular non-head node
168 * magic number without allocating any memory.
169 */
170#define BU_LIST_INIT_MAGIC(_headp, _magic) { \
171 BU_LIST_INIT((_headp)); \
172 BU_LIST_MAGIC_SET((_headp), (_magic)); \
173 }
174
175/**
176 * macro suitable for declaration statement zero-initialization of a
177 * bu_list struct, but not suitably for validation with
178 * BU_CK_LIST_HEAD() as the list pointers are NULL. does not allocate
179 * memory.
180 */
181#define BU_LIST_INIT_ZERO { 0, BU_LIST_NULL, BU_LIST_NULL }
182
183/**
184 * returns truthfully whether a bu_list has been initialized via
185 * BU_LIST_INIT(). lists initialized with BU_LIST_INIT_ZERO or
186 * zero-allocated will not return true as their forward/backward
187 * pointers reference nothing.
188 */
189#define BU_LIST_IS_INITIALIZED(_headp) (((struct bu_list *)(_headp) != BU_LIST_NULL) && LIKELY((_headp)->forw != BU_LIST_NULL))
190
191
192/**
193 * Insert "new" item in front of "old" item. Often, "old" is the
194 * head. To put the new item at the tail of the list, insert before
195 * the head, e.g. * BU_LIST_INSERT(&(head.l), &((p)->l));
196 */
197#define BU_LIST_INSERT(old, new) { \
198 BU_ASSERT((void *)(old) != (void *)NULL); \
199 BU_ASSERT((void *)(new) != (void *)NULL); \
200 (new)->back = (old)->back; \
201 (old)->back = (new); \
202 (new)->forw = (old); \
203 BU_ASSERT((void *)((new)->back) != (void *)NULL); \
204 (new)->back->forw = (new); }
205
206/**
207 * Append "new" item after "old" item. Often, "old" is the head. To
208 * put the new item at the head of the list, append after the head,
209 * e.g. * BU_LIST_APPEND(&(head.l), &((p)->l));
210 */
211#define BU_LIST_APPEND(old, new) { \
212 BU_ASSERT((void *)(old) != (void *)NULL); \
213 BU_ASSERT((void *)(new) != (void *)NULL); \
214 (new)->forw = (old)->forw; \
215 (new)->back = (old); \
216 (old)->forw = (new); \
217 BU_ASSERT((void *)((new)->forw) != (void *)NULL); \
218 (new)->forw->back = (new); }
219
220/**
221 * Dequeue "cur" item from anywhere in doubly-linked list
222 */
223#define BU_LIST_DEQUEUE(cur) { \
224 BU_ASSERT((void *)(cur) != (void *)NULL); \
225 if (LIKELY((cur)->forw != NULL)) (cur)->forw->back = (cur)->back; \
226 if (LIKELY((cur)->back != NULL)) (cur)->back->forw = (cur)->forw; \
227 (cur)->forw = (cur)->back = BU_LIST_NULL; /* sanity */ }
228
229/**
230 * Dequeue "cur" but do not fix its links
231 */
232#define BU_LIST_DQ(cur) {\
233 BU_ASSERT((void *)(cur) != (void *)NULL); \
234 if (LIKELY((cur)->forw != NULL)) (cur)->forw->back = (cur)->back; \
235 if (LIKELY((cur)->back != NULL)) (cur)->back->forw = (cur)->forw; }
236
237#define BU_LIST_DQ_T(cur, type) (\
238 (cur)->forw->back = (cur)->back, \
239 (cur)->back->forw = (cur)->forw, \
240 (type *)(cur))
241
242/**
243 * This version of BU_LIST_DEQUEUE uses the comma operator in order to
244 * return a typecast version of the dequeued pointer
245 */
246#define BU_LIST_DEQUEUE_T(cur, type) (\
247 (cur)->forw->back = (cur)->back, \
248 (cur)->back->forw = (cur)->forw, \
249 (cur)->forw = (cur)->back = BU_LIST_NULL, \
250 (type *)(cur))
251
252
253/**
254 * The Stack Discipline
255 *
256 * BU_LIST_PUSH places p at the tail of headp. BU_LIST_POP sets p to
257 * last element in headp's list (else NULL) and, if p is non-null,
258 * dequeues it.
259 */
260#define BU_LIST_PUSH(headp, p) \
261 BU_LIST_APPEND(headp, (struct bu_list *)(p))
262
263#define BU_LIST_POP(structure, headp, p) \
264 { \
265 if (BU_LIST_NON_EMPTY(headp)) { \
266 (p) = ((struct structure *)((headp)->forw)); \
267 BU_LIST_DEQUEUE((struct bu_list *)(p)); \
268 } else { \
269 (p) = (struct structure *) 0; \
270 } \
271 }
272
273#define BU_LIST_POP_T(headp, type) \
274 (type *)bu_list_pop(headp)
275
276/**
277 * "Bulk transfer" all elements from the list headed by src_headp onto
278 * the list headed by dest_headp, without examining every element in the
279 * list. src_headp is left with a valid but empty list.
280 *
281 * BU_LIST_INSERT_LIST places src_headp elements at head of dest_headp list,
282 * BU_LIST_APPEND_LIST places src_headp elements at end of dest_headp list.
283 */
284#define BU_LIST_INSERT_LIST(dest_headp, src_headp) \
285 if (LIKELY(BU_LIST_NON_EMPTY(src_headp))) { \
286 struct bu_list *_first = (src_headp)->forw; \
287 struct bu_list *_last = (src_headp)->back; \
288 (dest_headp)->forw->back = _last; \
289 _last->forw = (dest_headp)->forw; \
290 (dest_headp)->forw = _first; \
291 _first->back = (dest_headp); \
292 (src_headp)->forw = (src_headp)->back = (src_headp); \
293 }
294
295#define BU_LIST_APPEND_LIST(dest_headp, src_headp) \
296 if (LIKELY(BU_LIST_NON_EMPTY(src_headp))) {\
297 struct bu_list *_first = (src_headp)->forw; \
298 struct bu_list *_last = (src_headp)->back; \
299 _first->back = (dest_headp)->back; \
300 (dest_headp)->back->forw = _first; \
301 (dest_headp)->back = _last; \
302 _last->forw = (dest_headp); \
303 (src_headp)->forw = (src_headp)->back = (src_headp); \
304 }
305
306/**
307 * Test if a doubly linked list is empty, given head pointer
308 */
309#define BU_LIST_IS_EMPTY(headp) ((headp)->forw == (headp))
310#define BU_LIST_NON_EMPTY(headp) ((headp)->forw != (headp))
311#define BU_LIST_NON_EMPTY_P(p, structure, headp) \
312 (((p)=(struct structure *)((headp)->forw)) != (struct structure *)(headp))
313#define BU_LIST_IS_CLEAR(headp) ((headp)->magic == 0 && \
314 (headp)->forw == BU_LIST_NULL && \
315 (headp)->back == BU_LIST_NULL)
316
317/* Return re-cast pointer to first element on list.
318 * No checking is performed to see if list is empty.
319 */
320#define BU_LIST_LAST(structure, headp) \
321 ((struct structure *)((headp)->back))
322#define BU_LIST_BACK(structure, headp) \
323 ((struct structure *)((headp)->back))
324#define BU_LIST_PREV(structure, headp) \
325 ((struct structure *)((headp)->back))
326#define BU_LIST_FIRST(structure, headp) \
327 ((struct structure *)((headp)->forw))
328#define BU_LIST_FORW(structure, headp) \
329 ((struct structure *)((headp)->forw))
330#define BU_LIST_NEXT(structure, headp) \
331 ((struct structure *)((headp)->forw))
332
333/**
334 * Boolean test to see if current list element is the head
335 */
336#define BU_LIST_IS_HEAD(p, headp) \
337 (((struct bu_list *)(p)) == (struct bu_list *)(headp))
338#define BU_LIST_NOT_HEAD(p, headp) \
339 (!BU_LIST_IS_HEAD(p, headp))
340
341/**
342 * Boolean test to see if previous list element is the head
343 */
344#define BU_LIST_PREV_IS_HEAD(p, headp)\
345 (((struct bu_list *)(p))->back == (struct bu_list *)(headp))
346#define BU_LIST_PREV_NOT_HEAD(p, headp)\
347 (!BU_LIST_PREV_IS_HEAD(p, headp))
348
349/**
350 * Boolean test to see if the next list element is the head
351 */
352#define BU_LIST_NEXT_IS_HEAD(p, headp) \
353 (((struct bu_list *)(p))->forw == (struct bu_list *)(headp))
354#define BU_LIST_NEXT_NOT_HEAD(p, headp) \
355 (!BU_LIST_NEXT_IS_HEAD(p, headp))
356
357#define BU_LIST_EACH(headp, p, type) \
358 for ((p)=(type *)BU_LIST_FIRST(bu_list, headp); \
359 (p) && BU_LIST_NOT_HEAD(p, headp); \
360 (p)=(type *)BU_LIST_PNEXT(bu_list, p)) \
361
362#define BU_LIST_REVEACH(headp, p, type) \
363 for ((p)=(type *)BU_LIST_LAST(bu_list, headp); \
364 (p) && BU_LIST_NOT_HEAD(p, headp); \
365 (p)=(type *)BU_LIST_PREV(bu_list, ((struct bu_list *)(p)))) \
366
367#define BU_LIST_TAIL(headp, start, p, type) \
368 for ((p)=(type *)start; \
369 (p) && BU_LIST_NOT_HEAD(p, headp); \
370 (p)=(type *)BU_LIST_PNEXT(bu_list, (p)))
371
372/**
373 * Intended as innards for a for loop to visit all nodes on list, e.g.:
374 *
375 * for (BU_LIST_FOR(p, structure, headp)) {
376 * work_on(p);
377 * }
378 */
379#define BU_LIST_FOR(p, structure, headp) \
380 (p)=BU_LIST_FIRST(structure, headp); \
381 (p) && BU_LIST_NOT_HEAD(p, headp); \
382 (p)=BU_LIST_PNEXT(structure, p)
383
384#define BU_LIST_FOR_BACKWARDS(p, structure, headp) \
385 (p)=BU_LIST_LAST(structure, headp); \
386 (p) && BU_LIST_NOT_HEAD(p, headp); \
387 (p)=BU_LIST_PLAST(structure, p)
388
389/**
390 * Process all the list members except headp and the actual head. Useful
391 * when starting somewhere besides the head.
392 */
393#define BU_LIST_FOR_CIRC(p, structure, headp) \
394 (p)=BU_LIST_PNEXT_CIRC(structure, headp); \
395 (p) && BU_LIST_NOT_HEAD(p, headp); \
396 (p)=BU_LIST_PNEXT_CIRC(structure, p)
397
398/**
399 * Intended as innards for a for loop to visit elements of two lists
400 * in tandem, e.g.:
401 *
402 * for (BU_LIST_FOR2(p1, p2, structure, headp1, headp2)) {
403 * process(p1, p2);
404 * }
405 */
406#define BU_LIST_FOR2(p1, p2, structure, headp1, headp2) \
407 (p1)=BU_LIST_FIRST(structure, headp1), \
408 (p2)=BU_LIST_FIRST(structure, headp2); \
409 (p1) && BU_LIST_NOT_HEAD((struct bu_list *)(p1), (headp1)) && \
410 (p2) && BU_LIST_NOT_HEAD((struct bu_list *)(p2), (headp2)); \
411 (p1)=BU_LIST_NEXT(structure, (struct bu_list *)(p1)), \
412 (p2)=BU_LIST_NEXT(structure, (struct bu_list *)(p2))
413
414/**
415 * Innards for a while loop that constantly picks off the first
416 * element. Useful mostly for a loop that will dequeue every list
417 * element, e.g.:
418 *
419 * while (BU_LIST_WHILE(p, structure, headp)) {
420 *@n BU_LIST_DEQUEUE(&(p->l));
421 *@n free((char *)p);
422 *@n }
423 */
424#define BU_LIST_WHILE(p, structure, headp) \
425 (((p)=(struct structure *)((headp)->forw)) != (struct structure *)(headp))
426
427/**
428 * Return the magic number of the first (or last) item on a list
429 */
430#define BU_LIST_FIRST_MAGIC(headp) ((headp)->forw->magic)
431#define BU_LIST_LAST_MAGIC(headp) ((headp)->back->magic)
432
433/**
434 * Return pointer to next (or previous) element, which may be the head
435 */
436#define BU_LIST_PNEXT(structure, p) \
437 ((struct structure *)(((struct bu_list *)(p))->forw))
438#define BU_LIST_PLAST(structure, p) \
439 ((struct structure *)(((struct bu_list *)(p))->back))
440
441/**
442 * Return pointer two links away, which may include the head
443 */
444#define BU_LIST_PNEXT_PNEXT(structure, p) \
445 ((struct structure *)(((struct bu_list *)(p))->forw->forw))
446#define BU_LIST_PNEXT_PLAST(structure, p) \
447 ((struct structure *)(((struct bu_list *)(p))->forw->back))
448#define BU_LIST_PLAST_PNEXT(structure, p) \
449 ((struct structure *)(((struct bu_list *)(p))->back->forw))
450#define BU_LIST_PLAST_PLAST(structure, p) \
451 ((struct structure *)(((struct bu_list *)(p))->back->back))
452
453/**
454 * Return pointer to circular next element; i.e., ignoring the list head
455 */
456#define BU_LIST_PNEXT_CIRC(structure, p) \
457 ((BU_LIST_FIRST_MAGIC((struct bu_list *)(p)) == BU_LIST_HEAD_MAGIC) ? \
458 BU_LIST_PNEXT_PNEXT(structure, (struct bu_list *)(p)) : \
459 BU_LIST_PNEXT(structure, p))
460
461/**
462 * Return pointer to circular last element; i.e., ignoring the list head
463 */
464#define BU_LIST_PPREV_CIRC(structure, p) \
465 ((BU_LIST_LAST_MAGIC((struct bu_list *)(p)) == BU_LIST_HEAD_MAGIC) ? \
466 BU_LIST_PLAST_PLAST(structure, (struct bu_list *)(p)) : \
467 BU_LIST_PLAST(structure, p))
468
469/**
470 * Support for membership on multiple linked lists.
471 *
472 * When a structure of type '_type' contains more than one bu_list
473 * structure within it (such as the NMG edgeuse), this macro can be
474 * used to convert a pointer '_ptr2' to a "midway" bu_list structure
475 * (an element called '_name2' in structure '_type') back into a
476 * pointer to the overall enclosing structure. Examples:
477 *
478 * eu = BU_LIST_MAIN_PTR(edgeuse, midway, l2);
479 *
480 * eu1 = BU_LIST_MAIN_PTR(edgeuse, BU_LIST_FIRST(bu_list, &eg1->eu_hd2), l2);
481 *
482 * Files using BU_LIST_MAIN_PTR will need to include stddef.h
483 */
484#define BU_LIST_MAIN_PTR(_type, _ptr2, _name2) \
485 ((struct _type *)(((char *)(_ptr2)) - (bu_offsetof(struct _type, _name2) + bu_offsetof(struct bu_list, magic))))
486
487/**
488 * Creates and initializes a bu_list head structure
489 */
490BU_EXPORT extern struct bu_list *bu_list_new(void);
491
492/**
493 * Returns the results of BU_LIST_POP
494 */
495BU_EXPORT extern struct bu_list *bu_list_pop(struct bu_list *headp);
496
497/**
498 * Returns the number of elements on a bu_list brand linked list.
499 */
500BU_EXPORT extern int bu_list_len(const struct bu_list *headp);
501
502/**
503 * Reverses the order of elements in a bu_list linked list.
504 */
505BU_EXPORT extern void bu_list_reverse(struct bu_list *headp);
506
507/**
508 * Given a list of structures allocated with bu_malloc() or
509 * bu_calloc() enrolled on a bu_list head, walk the list and free the
510 * structures. This routine can only be used when the structures have
511 * no interior pointers.
512 */
513BU_EXPORT extern void bu_list_free(struct bu_list *headp);
514
515/**
516 * Simple parallel-safe routine for appending a data structure to the
517 * end of a bu_list doubly-linked list.
518 *
519 * @par Issues:
520 * Only one semaphore shared by all list heads.
521 * @n No portable way to notify waiting thread(s) that are sleeping
522 */
523BU_EXPORT extern void bu_list_parallel_append(struct bu_list *headp,
524 struct bu_list *itemp);
525
526/**
527 * Simple parallel-safe routine for dequeueing one data structure from
528 * the head of a bu_list doubly-linked list.
529 * If the list is empty, wait until some other thread puts something on
530 * the list.
531 *
532 * @par Issues:
533 * No portable way to not spin and burn CPU time while waiting
534 * @n for something to show up on the list.
535 */
536BU_EXPORT extern struct bu_list *bu_list_parallel_dequeue(struct bu_list *headp);
537
538/**
539 * Generic bu_list doubly-linked list checker.
540 */
541BU_EXPORT extern void bu_ck_list(const struct bu_list *headp,
542 const char *str);
543
544/**
545 * bu_list doubly-linked list checker which checks the magic number for
546 * all elements in the linked list
547 */
548BU_EXPORT extern void bu_ck_list_magic(const struct bu_list *headp,
549 const char *str,
550 const uint32_t magic);
551
552
553/** @} */
554
555__END_DECLS
556
557#endif /* BU_LIST_H */
558
559/*
560 * Local Variables:
561 * mode: C
562 * tab-width: 8
563 * indent-tabs-mode: t
564 * c-file-style: "stroustrup"
565 * End:
566 * ex: shiftwidth=4 tabstop=8
567 */
Header file for the BRL-CAD common definitions.
void bu_ck_list(const struct bu_list *headp, const char *str)
void bu_ck_list_magic(const struct bu_list *headp, const char *str, const uint32_t magic)
void bu_list_reverse(struct bu_list *headp)
int bu_list_len(const struct bu_list *headp)
struct bu_list * bu_list_parallel_dequeue(struct bu_list *headp)
struct bu_list * bu_list_pop(struct bu_list *headp)
void bu_list_free(struct bu_list *headp)
void bu_list_parallel_append(struct bu_list *headp, struct bu_list *itemp)
struct bu_list * bu_list_new(void)
Global registry of recognized magic numbers.
Definition: list.h:131
uint32_t magic
Magic # for mem id/check.
Definition: list.h:132
struct bu_list * forw
"forward", "next"
Definition: list.h:133
struct bu_list * back
"back", "last"
Definition: list.h:134