xref: /dflybsd-src/contrib/gdb-7/gdb/common/queue.h (revision de8e141f24382815c10a4012d209bbbf7abf1112)
1*ef5ccd6cSJohn Marino /* General queue data structure for GDB, the GNU debugger.
2*ef5ccd6cSJohn Marino 
3*ef5ccd6cSJohn Marino    Copyright (C) 2012-2013 Free Software Foundation, Inc.
4*ef5ccd6cSJohn Marino 
5*ef5ccd6cSJohn Marino    This file is part of GDB.
6*ef5ccd6cSJohn Marino 
7*ef5ccd6cSJohn Marino    This program is free software; you can redistribute it and/or modify
8*ef5ccd6cSJohn Marino    it under the terms of the GNU General Public License as published by
9*ef5ccd6cSJohn Marino    the Free Software Foundation; either version 3 of the License, or
10*ef5ccd6cSJohn Marino    (at your option) any later version.
11*ef5ccd6cSJohn Marino 
12*ef5ccd6cSJohn Marino    This program is distributed in the hope that it will be useful,
13*ef5ccd6cSJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*ef5ccd6cSJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*ef5ccd6cSJohn Marino    GNU General Public License for more details.
16*ef5ccd6cSJohn Marino 
17*ef5ccd6cSJohn Marino    You should have received a copy of the GNU General Public License
18*ef5ccd6cSJohn Marino    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19*ef5ccd6cSJohn Marino 
20*ef5ccd6cSJohn Marino #ifndef QUEUE_H
21*ef5ccd6cSJohn Marino #define QUEUE_H
22*ef5ccd6cSJohn Marino 
23*ef5ccd6cSJohn Marino #include "libiberty.h" /* xmalloc */
24*ef5ccd6cSJohn Marino #include "gdb_assert.h"
25*ef5ccd6cSJohn Marino 
26*ef5ccd6cSJohn Marino /* These macros implement functions and structs for a general queue.
27*ef5ccd6cSJohn Marino    Macro 'DEFINE_QUEUE_P(TYPEDEF)' is to define the new queue type for
28*ef5ccd6cSJohn Marino    TYPEDEF', and macro 'DECLARE_QUEUE_P' is to declare external queue
29*ef5ccd6cSJohn Marino    APIs.  The character P indicates TYPEDEF is a pointer (P).  The
30*ef5ccd6cSJohn Marino    counterpart on object (O) and integer (I) are not implemented.
31*ef5ccd6cSJohn Marino 
32*ef5ccd6cSJohn Marino    An example of their use would be,
33*ef5ccd6cSJohn Marino 
34*ef5ccd6cSJohn Marino    typedef struct foo
35*ef5ccd6cSJohn Marino    {} *foo_p;
36*ef5ccd6cSJohn Marino 
37*ef5ccd6cSJohn Marino    DEFINE_QUEUE_P (foo_p);
38*ef5ccd6cSJohn Marino    // A pointer to a queue of foo pointers.  FOO_XFREE is a destructor
39*ef5ccd6cSJohn Marino    // function for foo instances in queue.
40*ef5ccd6cSJohn Marino    QUEUE(foo_p) *foo_queue = QUEUE_alloc (foo_p, foo_xfree);
41*ef5ccd6cSJohn Marino 
42*ef5ccd6cSJohn Marino    foo_p foo_var_p;
43*ef5ccd6cSJohn Marino    // Enqueue and Dequeue
44*ef5ccd6cSJohn Marino    QUEUE_enque (foo_p, foo_queue, foo_var_p);
45*ef5ccd6cSJohn Marino    foo_var_p = QUEUE_deque (foo_p, foo_queue);
46*ef5ccd6cSJohn Marino 
47*ef5ccd6cSJohn Marino    static int visit_foo (QUEUE (foo_p) *q, QUEUE_ITER (foo_p) *iter,
48*ef5ccd6cSJohn Marino 			foo_p f, void *data)
49*ef5ccd6cSJohn Marino    {
50*ef5ccd6cSJohn Marino      return 1;
51*ef5ccd6cSJohn Marino    }
52*ef5ccd6cSJohn Marino    // Iterate over queue.
53*ef5ccd6cSJohn Marino    QUEUE_iterate (foo_p, foo_queue, visit_foo, &param);
54*ef5ccd6cSJohn Marino 
55*ef5ccd6cSJohn Marino    QUEUE_free (foo_p, foo_queue);  // Free queue.  */
56*ef5ccd6cSJohn Marino 
57*ef5ccd6cSJohn Marino /* Typical enqueue operation.  Put V into queue Q.  */
58*ef5ccd6cSJohn Marino #define QUEUE_enque(TYPE, Q, V) queue_ ## TYPE ## _enque ((Q), (V))
59*ef5ccd6cSJohn Marino 
60*ef5ccd6cSJohn Marino /* Typical dequeue operation.  Return head element of queue Q and
61*ef5ccd6cSJohn Marino    remove it.  Q must not be empty.  */
62*ef5ccd6cSJohn Marino #define QUEUE_deque(TYPE, Q) queue_ ## TYPE ## _deque (Q)
63*ef5ccd6cSJohn Marino 
64*ef5ccd6cSJohn Marino /* Return the head element, but don't remove it from the queue.
65*ef5ccd6cSJohn Marino    Q must not be empty.  */
66*ef5ccd6cSJohn Marino #define QUEUE_peek(TYPE, Q) queue_ ## TYPE ## _peek (Q)
67*ef5ccd6cSJohn Marino 
68*ef5ccd6cSJohn Marino /* Return true if queue Q is empty.  */
69*ef5ccd6cSJohn Marino #define QUEUE_is_empty(TYPE, Q) queue_ ## TYPE ## _is_empty (Q)
70*ef5ccd6cSJohn Marino 
71*ef5ccd6cSJohn Marino /* Allocate memory for queue.  FREE_FUNC is a function to release the
72*ef5ccd6cSJohn Marino    data put in each queue element.  */
73*ef5ccd6cSJohn Marino #define QUEUE_alloc(TYPE, FREE_FUNC) queue_ ## TYPE ## _alloc (FREE_FUNC)
74*ef5ccd6cSJohn Marino 
75*ef5ccd6cSJohn Marino /* Length of queue Q.  */
76*ef5ccd6cSJohn Marino #define QUEUE_length(TYPE, Q) queue_ ## TYPE ## _length (Q)
77*ef5ccd6cSJohn Marino 
78*ef5ccd6cSJohn Marino /* Free queue Q.  Q's free_func is called once for each element.  */
79*ef5ccd6cSJohn Marino #define QUEUE_free(TYPE, Q) queue_ ## TYPE ## _free (Q)
80*ef5ccd6cSJohn Marino 
81*ef5ccd6cSJohn Marino /* Iterate over elements in the queue Q and call function OPERATE on
82*ef5ccd6cSJohn Marino    each element.  It is allowed to remove element by OPERATE.  OPERATE
83*ef5ccd6cSJohn Marino    returns false to terminate the iteration and true to continue the
84*ef5ccd6cSJohn Marino    iteration.  Return false if iteration is terminated by function
85*ef5ccd6cSJohn Marino    OPERATE, otherwise return true.  */
86*ef5ccd6cSJohn Marino #define QUEUE_iterate(TYPE, Q, OPERATE, PARAM)	\
87*ef5ccd6cSJohn Marino   queue_ ## TYPE ## _iterate ((Q), (OPERATE), (PARAM))
88*ef5ccd6cSJohn Marino 
89*ef5ccd6cSJohn Marino /* Remove the element per the state of iterator ITER from queue Q.
90*ef5ccd6cSJohn Marino    Leave the caller to release the data in the queue element.  */
91*ef5ccd6cSJohn Marino #define QUEUE_remove_elem(TYPE, Q, ITER) \
92*ef5ccd6cSJohn Marino   queue_ ## TYPE ## _remove_elem ((Q), (ITER))
93*ef5ccd6cSJohn Marino 
94*ef5ccd6cSJohn Marino /* Define a new queue implementation.  */
95*ef5ccd6cSJohn Marino 
96*ef5ccd6cSJohn Marino #define QUEUE(TYPE) struct queue_ ## TYPE
97*ef5ccd6cSJohn Marino #define QUEUE_ELEM(TYPE) struct queue_elem_ ## TYPE
98*ef5ccd6cSJohn Marino #define QUEUE_ITER(TYPE) struct queue_iter_ ## TYPE
99*ef5ccd6cSJohn Marino #define QUEUE_ITER_FUNC(TYPE) queue_ ## TYPE ## _operate_func
100*ef5ccd6cSJohn Marino 
101*ef5ccd6cSJohn Marino #define DEFINE_QUEUE_P(TYPE)			\
102*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE)				\
103*ef5ccd6cSJohn Marino {						\
104*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *next;			\
105*ef5ccd6cSJohn Marino 						\
106*ef5ccd6cSJohn Marino   TYPE data;					\
107*ef5ccd6cSJohn Marino };						\
108*ef5ccd6cSJohn Marino 						\
109*ef5ccd6cSJohn Marino /* Queue iterator.  */				\
110*ef5ccd6cSJohn Marino QUEUE_ITER (TYPE)				\
111*ef5ccd6cSJohn Marino {						\
112*ef5ccd6cSJohn Marino   /* The current element during traverse.  */	\
113*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *p;			\
114*ef5ccd6cSJohn Marino   /* The previous element of P.  */		\
115*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *prev;			\
116*ef5ccd6cSJohn Marino };						\
117*ef5ccd6cSJohn Marino 						\
118*ef5ccd6cSJohn Marino QUEUE(TYPE)					\
119*ef5ccd6cSJohn Marino {						\
120*ef5ccd6cSJohn Marino   /*  The head and tail of the queue.  */	\
121*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *head;			\
122*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *tail;			\
123*ef5ccd6cSJohn Marino   /* Function to release the data put in each	\
124*ef5ccd6cSJohn Marino      queue element.  */			\
125*ef5ccd6cSJohn Marino   void (*free_func) (TYPE);			\
126*ef5ccd6cSJohn Marino };						\
127*ef5ccd6cSJohn Marino 						\
128*ef5ccd6cSJohn Marino void									\
129*ef5ccd6cSJohn Marino queue_ ## TYPE ## _enque (QUEUE (TYPE) *q, TYPE v)			\
130*ef5ccd6cSJohn Marino {									\
131*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *p							\
132*ef5ccd6cSJohn Marino     = xmalloc (sizeof (QUEUE_ELEM (TYPE)));				\
133*ef5ccd6cSJohn Marino 									\
134*ef5ccd6cSJohn Marino   gdb_assert (q != NULL);						\
135*ef5ccd6cSJohn Marino   p->data = v;								\
136*ef5ccd6cSJohn Marino   p->next = NULL;							\
137*ef5ccd6cSJohn Marino   if (q->tail == NULL)							\
138*ef5ccd6cSJohn Marino     {									\
139*ef5ccd6cSJohn Marino       q->tail = p;							\
140*ef5ccd6cSJohn Marino       q->head = p;							\
141*ef5ccd6cSJohn Marino     }									\
142*ef5ccd6cSJohn Marino   else									\
143*ef5ccd6cSJohn Marino     {									\
144*ef5ccd6cSJohn Marino       q->tail->next = p;						\
145*ef5ccd6cSJohn Marino       q->tail = p;							\
146*ef5ccd6cSJohn Marino     }									\
147*ef5ccd6cSJohn Marino }									\
148*ef5ccd6cSJohn Marino 									\
149*ef5ccd6cSJohn Marino TYPE									\
150*ef5ccd6cSJohn Marino queue_ ## TYPE ## _deque (QUEUE (TYPE) *q)				\
151*ef5ccd6cSJohn Marino {									\
152*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *p;						\
153*ef5ccd6cSJohn Marino   TYPE v;								\
154*ef5ccd6cSJohn Marino 									\
155*ef5ccd6cSJohn Marino   gdb_assert (q != NULL);						\
156*ef5ccd6cSJohn Marino   p = q->head;								\
157*ef5ccd6cSJohn Marino   gdb_assert (p != NULL);						\
158*ef5ccd6cSJohn Marino 									\
159*ef5ccd6cSJohn Marino   if (q->head == q->tail)						\
160*ef5ccd6cSJohn Marino     {									\
161*ef5ccd6cSJohn Marino       q->head = NULL;							\
162*ef5ccd6cSJohn Marino       q->tail = NULL;							\
163*ef5ccd6cSJohn Marino     }									\
164*ef5ccd6cSJohn Marino   else									\
165*ef5ccd6cSJohn Marino     q->head = q->head->next;						\
166*ef5ccd6cSJohn Marino 									\
167*ef5ccd6cSJohn Marino   v = p->data;								\
168*ef5ccd6cSJohn Marino 									\
169*ef5ccd6cSJohn Marino   xfree (p);								\
170*ef5ccd6cSJohn Marino   return v;								\
171*ef5ccd6cSJohn Marino }									\
172*ef5ccd6cSJohn Marino 									\
173*ef5ccd6cSJohn Marino TYPE									\
174*ef5ccd6cSJohn Marino queue_ ## TYPE ## _peek (QUEUE (TYPE) *q)				\
175*ef5ccd6cSJohn Marino {									\
176*ef5ccd6cSJohn Marino   gdb_assert (q != NULL);						\
177*ef5ccd6cSJohn Marino   gdb_assert (q->head != NULL);					\
178*ef5ccd6cSJohn Marino   return q->head->data;						\
179*ef5ccd6cSJohn Marino }									\
180*ef5ccd6cSJohn Marino 									\
181*ef5ccd6cSJohn Marino int									\
182*ef5ccd6cSJohn Marino queue_ ## TYPE ## _is_empty (QUEUE (TYPE) *q)				\
183*ef5ccd6cSJohn Marino {									\
184*ef5ccd6cSJohn Marino   gdb_assert (q != NULL);						\
185*ef5ccd6cSJohn Marino   return q->head == NULL;						\
186*ef5ccd6cSJohn Marino }									\
187*ef5ccd6cSJohn Marino 									\
188*ef5ccd6cSJohn Marino void									\
189*ef5ccd6cSJohn Marino queue_ ## TYPE ## _remove_elem (QUEUE (TYPE) *q,			\
190*ef5ccd6cSJohn Marino 				QUEUE_ITER (TYPE) *iter)		\
191*ef5ccd6cSJohn Marino {									\
192*ef5ccd6cSJohn Marino   gdb_assert (q != NULL);						\
193*ef5ccd6cSJohn Marino   gdb_assert (iter != NULL && iter->p != NULL);			\
194*ef5ccd6cSJohn Marino 									\
195*ef5ccd6cSJohn Marino   if (iter->p == q->head || iter->p == q->tail)			\
196*ef5ccd6cSJohn Marino     {									\
197*ef5ccd6cSJohn Marino       if (iter->p == q->head)						\
198*ef5ccd6cSJohn Marino 	q->head = iter->p->next;					\
199*ef5ccd6cSJohn Marino       if (iter->p == q->tail)						\
200*ef5ccd6cSJohn Marino 	q->tail = iter->prev;						\
201*ef5ccd6cSJohn Marino     }									\
202*ef5ccd6cSJohn Marino   else									\
203*ef5ccd6cSJohn Marino     iter->prev->next = iter->p->next;					\
204*ef5ccd6cSJohn Marino 									\
205*ef5ccd6cSJohn Marino   xfree (iter->p);							\
206*ef5ccd6cSJohn Marino   /* Indicate that ITER->p has been deleted from QUEUE q.  */		\
207*ef5ccd6cSJohn Marino   iter->p = NULL;							\
208*ef5ccd6cSJohn Marino }									\
209*ef5ccd6cSJohn Marino 									\
210*ef5ccd6cSJohn Marino int									\
211*ef5ccd6cSJohn Marino queue_ ## TYPE ## _iterate (QUEUE (TYPE) *q,				\
212*ef5ccd6cSJohn Marino 			    QUEUE_ITER_FUNC (TYPE) operate,		\
213*ef5ccd6cSJohn Marino 			    void *data)				\
214*ef5ccd6cSJohn Marino {									\
215*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *next = NULL;					\
216*ef5ccd6cSJohn Marino   QUEUE_ITER (TYPE) iter = { NULL, NULL };				\
217*ef5ccd6cSJohn Marino 									\
218*ef5ccd6cSJohn Marino   gdb_assert (q != NULL);						\
219*ef5ccd6cSJohn Marino 									\
220*ef5ccd6cSJohn Marino   for (iter.p = q->head; iter.p != NULL; iter.p = next)		\
221*ef5ccd6cSJohn Marino     {									\
222*ef5ccd6cSJohn Marino       next = iter.p->next;						\
223*ef5ccd6cSJohn Marino       if (!operate (q, &iter, iter.p->data, data))			\
224*ef5ccd6cSJohn Marino 	return 0;							\
225*ef5ccd6cSJohn Marino       /* ITER.P was not deleted by function OPERATE.  */		\
226*ef5ccd6cSJohn Marino       if (iter.p != NULL)						\
227*ef5ccd6cSJohn Marino 	iter.prev = iter.p;						\
228*ef5ccd6cSJohn Marino     }									\
229*ef5ccd6cSJohn Marino   return 1;								\
230*ef5ccd6cSJohn Marino }									\
231*ef5ccd6cSJohn Marino 									\
232*ef5ccd6cSJohn Marino QUEUE (TYPE) *								\
233*ef5ccd6cSJohn Marino queue_ ## TYPE ## _alloc (void (*free_func) (TYPE))			\
234*ef5ccd6cSJohn Marino {									\
235*ef5ccd6cSJohn Marino   QUEUE (TYPE) *q;							\
236*ef5ccd6cSJohn Marino 									\
237*ef5ccd6cSJohn Marino   q = (QUEUE (TYPE) *) xmalloc (sizeof (QUEUE (TYPE)));		\
238*ef5ccd6cSJohn Marino   q->head = NULL;							\
239*ef5ccd6cSJohn Marino   q->tail = NULL;							\
240*ef5ccd6cSJohn Marino   q->free_func = free_func;						\
241*ef5ccd6cSJohn Marino   return q;								\
242*ef5ccd6cSJohn Marino }									\
243*ef5ccd6cSJohn Marino 									\
244*ef5ccd6cSJohn Marino int									\
245*ef5ccd6cSJohn Marino queue_ ## TYPE ## _length (QUEUE (TYPE) *q)				\
246*ef5ccd6cSJohn Marino {									\
247*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *p;						\
248*ef5ccd6cSJohn Marino   int len = 0;								\
249*ef5ccd6cSJohn Marino 									\
250*ef5ccd6cSJohn Marino   gdb_assert (q != NULL);						\
251*ef5ccd6cSJohn Marino 									\
252*ef5ccd6cSJohn Marino   for (p = q->head; p != NULL; p = p->next)				\
253*ef5ccd6cSJohn Marino     len++;								\
254*ef5ccd6cSJohn Marino 									\
255*ef5ccd6cSJohn Marino   return len;								\
256*ef5ccd6cSJohn Marino }									\
257*ef5ccd6cSJohn Marino 									\
258*ef5ccd6cSJohn Marino void									\
259*ef5ccd6cSJohn Marino queue_ ## TYPE ## _free (QUEUE (TYPE) *q)				\
260*ef5ccd6cSJohn Marino {									\
261*ef5ccd6cSJohn Marino   QUEUE_ELEM (TYPE) *p, *next;						\
262*ef5ccd6cSJohn Marino 									\
263*ef5ccd6cSJohn Marino   gdb_assert (q != NULL);						\
264*ef5ccd6cSJohn Marino 									\
265*ef5ccd6cSJohn Marino   for (p = q->head; p != NULL; p = next)				\
266*ef5ccd6cSJohn Marino     {									\
267*ef5ccd6cSJohn Marino       next = p->next;							\
268*ef5ccd6cSJohn Marino       if (q->free_func)						\
269*ef5ccd6cSJohn Marino 	q->free_func (p->data);					\
270*ef5ccd6cSJohn Marino       xfree (p);							\
271*ef5ccd6cSJohn Marino     }									\
272*ef5ccd6cSJohn Marino   xfree (q);								\
273*ef5ccd6cSJohn Marino }									\
274*ef5ccd6cSJohn Marino 
275*ef5ccd6cSJohn Marino /* External declarations for queue functions.  */
276*ef5ccd6cSJohn Marino #define DECLARE_QUEUE_P(TYPE)					\
277*ef5ccd6cSJohn Marino QUEUE (TYPE);							\
278*ef5ccd6cSJohn Marino QUEUE_ELEM (TYPE);						\
279*ef5ccd6cSJohn Marino QUEUE_ITER (TYPE);						\
280*ef5ccd6cSJohn Marino extern void							\
281*ef5ccd6cSJohn Marino   queue_ ## TYPE ## _enque (QUEUE (TYPE) *q, TYPE v);		\
282*ef5ccd6cSJohn Marino extern TYPE							\
283*ef5ccd6cSJohn Marino   queue_ ## TYPE ## _deque (QUEUE (TYPE) *q);			\
284*ef5ccd6cSJohn Marino extern int queue_ ## TYPE ## _is_empty (QUEUE (TYPE) *q);	\
285*ef5ccd6cSJohn Marino extern QUEUE (TYPE) *						\
286*ef5ccd6cSJohn Marino   queue_ ## TYPE ## _alloc (void (*free_func) (TYPE));		\
287*ef5ccd6cSJohn Marino extern int queue_ ## TYPE ## _length (QUEUE (TYPE) *q);	\
288*ef5ccd6cSJohn Marino extern TYPE							\
289*ef5ccd6cSJohn Marino   queue_ ## TYPE ## _peek (QUEUE (TYPE) *q);			\
290*ef5ccd6cSJohn Marino extern void queue_ ## TYPE ## _free (QUEUE (TYPE) *q);		\
291*ef5ccd6cSJohn Marino typedef int QUEUE_ITER_FUNC(TYPE) (QUEUE (TYPE) *,		\
292*ef5ccd6cSJohn Marino 				   QUEUE_ITER (TYPE) *,	\
293*ef5ccd6cSJohn Marino 				   TYPE,			\
294*ef5ccd6cSJohn Marino 				   void *);			\
295*ef5ccd6cSJohn Marino extern int							\
296*ef5ccd6cSJohn Marino   queue_ ## TYPE ## _iterate (QUEUE (TYPE) *q,			\
297*ef5ccd6cSJohn Marino 			      QUEUE_ITER_FUNC (TYPE) operate,	\
298*ef5ccd6cSJohn Marino 			      void *);				\
299*ef5ccd6cSJohn Marino extern void							\
300*ef5ccd6cSJohn Marino   queue_ ## TYPE ## _remove_elem (QUEUE (TYPE) *q,		\
301*ef5ccd6cSJohn Marino 				  QUEUE_ITER (TYPE) *iter);	\
302*ef5ccd6cSJohn Marino 
303*ef5ccd6cSJohn Marino #endif /* QUEUE_H */
304