1CIRCLEQ(3) Library Functions Manual CIRCLEQ(3)
2
3
4
6 CIRCLEQ_EMPTY, CIRCLEQ_ENTRY, CIRCLEQ_FIRST, CIRCLEQ_FOREACH, CIR‐
7 CLEQ_FOREACH_REVERSE, CIRCLEQ_HEAD, CIRCLEQ_HEAD_INITIALIZER, CIR‐
8 CLEQ_INIT, CIRCLEQ_INSERT_AFTER, CIRCLEQ_INSERT_BEFORE, CIRCLEQ_IN‐
9 SERT_HEAD, CIRCLEQ_INSERT_TAIL, CIRCLEQ_LAST, CIRCLEQ_LOOP_NEXT, CIR‐
10 CLEQ_LOOP_PREV, CIRCLEQ_NEXT, CIRCLEQ_PREV, CIRCLEQ_REMOVE - implemen‐
11 tation of a doubly linked circular queue
12
14 Standard C library (libc, -lc)
15
17 #include <sys/queue.h>
18
19 CIRCLEQ_ENTRY(TYPE);
20
21 CIRCLEQ_HEAD(HEADNAME, TYPE);
22 CIRCLEQ_HEAD CIRCLEQ_HEAD_INITIALIZER(CIRCLEQ_HEAD head);
23 void CIRCLEQ_INIT(CIRCLEQ_HEAD *head);
24
25 int CIRCLEQ_EMPTY(CIRCLEQ_HEAD *head);
26
27 void CIRCLEQ_INSERT_HEAD(CIRCLEQ_HEAD *head,
28 struct TYPE *elm, CIRCLEQ_ENTRY NAME);
29 void CIRCLEQ_INSERT_TAIL(CIRCLEQ_HEAD *head,
30 struct TYPE *elm, CIRCLEQ_ENTRY NAME);
31 void CIRCLEQ_INSERT_BEFORE(CIRCLEQ_HEAD *head, struct TYPE *listelm,
32 struct TYPE *elm, CIRCLEQ_ENTRY NAME);
33 void CIRCLEQ_INSERT_AFTER(CIRCLEQ_HEAD *head, struct TYPE *listelm,
34 struct TYPE *elm, CIRCLEQ_ENTRY NAME);
35
36 struct TYPE *CIRCLEQ_FIRST(CIRCLEQ_HEAD *head);
37 struct TYPE *CIRCLEQ_LAST(CIRCLEQ_HEAD *head);
38 struct TYPE *CIRCLEQ_PREV(struct TYPE *elm, CIRCLEQ_ENTRY NAME);
39 struct TYPE *CIRCLEQ_NEXT(struct TYPE *elm, CIRCLEQ_ENTRY NAME);
40 struct TYPE *CIRCLEQ_LOOP_PREV(CIRCLEQ_HEAD *head,
41 struct TYPE *elm, CIRCLEQ_ENTRY NAME);
42 struct TYPE *CIRCLEQ_LOOP_NEXT(CIRCLEQ_HEAD *head,
43 struct TYPE *elm, CIRCLEQ_ENTRY NAME);
44
45 CIRCLEQ_FOREACH(struct TYPE *var, CIRCLEQ_HEAD *head,
46 CIRCLEQ_ENTRY NAME);
47 CIRCLEQ_FOREACH_REVERSE(struct TYPE *var, CIRCLEQ_HEAD *head,
48 CIRCLEQ_ENTRY NAME);
49
50 void CIRCLEQ_REMOVE(CIRCLEQ_HEAD *head, struct TYPE *elm,
51 CIRCLEQ_ENTRY NAME);
52
54 These macros define and operate on doubly linked circular queues.
55
56 In the macro definitions, TYPE is the name of a user-defined structure,
57 that must contain a field of type CIRCLEQ_ENTRY, named NAME. The argu‐
58 ment HEADNAME is the name of a user-defined structure that must be de‐
59 clared using the macro CIRCLEQ_HEAD().
60
61 Creation
62 A circular queue is headed by a structure defined by the CIRCLEQ_HEAD()
63 macro. This structure contains a pair of pointers, one to the first
64 element in the queue and the other to the last element in the queue.
65 The elements are doubly linked so that an arbitrary element can be re‐
66 moved without traversing the queue. New elements can be added to the
67 queue after an existing element, before an existing element, at the
68 head of the queue, or at the end of the queue. A CIRCLEQ_HEAD struc‐
69 ture is declared as follows:
70
71 CIRCLEQ_HEAD(HEADNAME, TYPE) head;
72
73 where struct HEADNAME is the structure to be defined, and struct TYPE
74 is the type of the elements to be linked into the queue. A pointer to
75 the head of the queue can later be declared as:
76
77 struct HEADNAME *headp;
78
79 (The names head and headp are user selectable.)
80
81 CIRCLEQ_ENTRY() declares a structure that connects the elements in the
82 queue.
83
84 CIRCLEQ_HEAD_INITIALIZER() evaluates to an initializer for the queue
85 head.
86
87 CIRCLEQ_INIT() initializes the queue referenced by head.
88
89 CIRCLEQ_EMPTY() evaluates to true if there are no items on the queue.
90
91 Insertion
92 CIRCLEQ_INSERT_HEAD() inserts the new element elm at the head of the
93 queue.
94
95 CIRCLEQ_INSERT_TAIL() inserts the new element elm at the end of the
96 queue.
97
98 CIRCLEQ_INSERT_BEFORE() inserts the new element elm before the element
99 listelm.
100
101 CIRCLEQ_INSERT_AFTER() inserts the new element elm after the element
102 listelm.
103
104 Traversal
105 CIRCLEQ_FIRST() returns the first item on the queue.
106
107 CIRCLEQ_LAST() returns the last item on the queue.
108
109 CIRCLEQ_PREV() returns the previous item on the queue, or &head if this
110 item is the first one.
111
112 CIRCLEQ_NEXT() returns the next item on the queue, or &head if this
113 item is the last one.
114
115 CIRCLEQ_LOOP_PREV() returns the previous item on the queue. If elm is
116 the first element on the queue, the last element is returned.
117
118 CIRCLEQ_LOOP_NEXT() returns the next item on the queue. If elm is the
119 last element on the queue, the first element is returned.
120
121 CIRCLEQ_FOREACH() traverses the queue referenced by head in the forward
122 direction, assigning each element in turn to var. var is set to &head
123 if the loop completes normally, or if there were no elements.
124
125 CIRCLEQ_FOREACH_REVERSE() traverses the queue referenced by head in the
126 reverse direction, assigning each element in turn to var.
127
128 Removal
129 CIRCLEQ_REMOVE() removes the element elm from the queue.
130
132 CIRCLEQ_EMPTY() returns nonzero if the queue is empty, and zero if the
133 queue contains at least one entry.
134
135 CIRCLEQ_FIRST(), CIRCLEQ_LAST(), CIRCLEQ_LOOP_PREV(), and CIR‐
136 CLEQ_LOOP_NEXT() return a pointer to the first, last, previous, or next
137 TYPE structure, respectively.
138
139 CIRCLEQ_PREV(), and CIRCLEQ_NEXT() are similar to their CIR‐
140 CLEQ_LOOP_*() counterparts, except that if the argument is the first or
141 last element, respectively, they return &head.
142
143 CIRCLEQ_HEAD_INITIALIZER() returns an initializer that can be assigned
144 to the queue head.
145
147 BSD.
148
150 CIRCLEQ_FOREACH() and CIRCLEQ_FOREACH_REVERSE() don't allow var to be
151 removed or freed within the loop, as it would interfere with the tra‐
152 versal. CIRCLEQ_FOREACH_SAFE() and CIRCLEQ_FOREACH_REVERSE_SAFE(),
153 which are present on the BSDs but are not present in glibc, fix this
154 limitation by allowing var to safely be removed from the list and freed
155 from within the loop without interfering with the traversal.
156
158 #include <stddef.h>
159 #include <stdio.h>
160 #include <stdlib.h>
161 #include <sys/queue.h>
162
163 struct entry {
164 int data;
165 CIRCLEQ_ENTRY(entry) entries; /* Queue */
166 };
167
168 CIRCLEQ_HEAD(circlehead, entry);
169
170 int
171 main(void)
172 {
173 struct entry *n1, *n2, *n3, *np;
174 struct circlehead head; /* Queue head */
175 int i;
176
177 CIRCLEQ_INIT(&head); /* Initialize the queue */
178
179 n1 = malloc(sizeof(struct entry)); /* Insert at the head */
180 CIRCLEQ_INSERT_HEAD(&head, n1, entries);
181
182 n1 = malloc(sizeof(struct entry)); /* Insert at the tail */
183 CIRCLEQ_INSERT_TAIL(&head, n1, entries);
184
185 n2 = malloc(sizeof(struct entry)); /* Insert after */
186 CIRCLEQ_INSERT_AFTER(&head, n1, n2, entries);
187
188 n3 = malloc(sizeof(struct entry)); /* Insert before */
189 CIRCLEQ_INSERT_BEFORE(&head, n2, n3, entries);
190
191 CIRCLEQ_REMOVE(&head, n2, entries); /* Deletion */
192 free(n2);
193 /* Forward traversal */
194 i = 0;
195 CIRCLEQ_FOREACH(np, &head, entries)
196 np->data = i++;
197 /* Reverse traversal */
198 CIRCLEQ_FOREACH_REVERSE(np, &head, entries)
199 printf("%i\n", np->data);
200 /* Queue deletion */
201 n1 = CIRCLEQ_FIRST(&head);
202 while (n1 != (void *)&head) {
203 n2 = CIRCLEQ_NEXT(n1, entries);
204 free(n1);
205 n1 = n2;
206 }
207 CIRCLEQ_INIT(&head);
208
209 exit(EXIT_SUCCESS);
210 }
211
213 insque(3), queue(7)
214
215
216
217Linux man-pages 6.04 2023-03-30 CIRCLEQ(3)