GDB (API)
/home/stan/gdb/src/gdb/common/queue.h
Go to the documentation of this file.
00001 /* General queue data structure for GDB, the GNU debugger.
00002 
00003    Copyright (C) 2012-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #ifndef QUEUE_H
00021 #define QUEUE_H
00022 
00023 #include "libiberty.h" /* xmalloc */
00024 #include "gdb_assert.h"
00025 
00026 /* These macros implement functions and structs for a general queue.
00027    Macro 'DEFINE_QUEUE_P(TYPEDEF)' is to define the new queue type for
00028    TYPEDEF', and macro 'DECLARE_QUEUE_P' is to declare external queue
00029    APIs.  The character P indicates TYPEDEF is a pointer (P).  The
00030    counterpart on object (O) and integer (I) are not implemented.
00031 
00032    An example of their use would be,
00033 
00034    typedef struct foo
00035    {} *foo_p;
00036 
00037    DEFINE_QUEUE_P (foo_p);
00038    // A pointer to a queue of foo pointers.  FOO_XFREE is a destructor
00039    // function for foo instances in queue.
00040    QUEUE(foo_p) *foo_queue = QUEUE_alloc (foo_p, foo_xfree);
00041 
00042    foo_p foo_var_p;
00043    // Enqueue and Dequeue
00044    QUEUE_enque (foo_p, foo_queue, foo_var_p);
00045    foo_var_p = QUEUE_deque (foo_p, foo_queue);
00046 
00047    static int visit_foo (QUEUE (foo_p) *q, QUEUE_ITER (foo_p) *iter,
00048                         foo_p f, void *data)
00049    {
00050      return 1;
00051    }
00052    // Iterate over queue.
00053    QUEUE_iterate (foo_p, foo_queue, visit_foo, &param);
00054 
00055    QUEUE_free (foo_p, foo_queue);  // Free queue.  */
00056 
00057 /* Typical enqueue operation.  Put V into queue Q.  */
00058 #define QUEUE_enque(TYPE, Q, V) queue_ ## TYPE ## _enque ((Q), (V))
00059 
00060 /* Typical dequeue operation.  Return head element of queue Q and
00061    remove it.  Q must not be empty.  */
00062 #define QUEUE_deque(TYPE, Q) queue_ ## TYPE ## _deque (Q)
00063 
00064 /* Return the head element, but don't remove it from the queue.
00065    Q must not be empty.  */
00066 #define QUEUE_peek(TYPE, Q) queue_ ## TYPE ## _peek (Q)
00067 
00068 /* Return true if queue Q is empty.  */
00069 #define QUEUE_is_empty(TYPE, Q) queue_ ## TYPE ## _is_empty (Q)
00070 
00071 /* Allocate memory for queue.  FREE_FUNC is a function to release the
00072    data put in each queue element.  */
00073 #define QUEUE_alloc(TYPE, FREE_FUNC) queue_ ## TYPE ## _alloc (FREE_FUNC)
00074 
00075 /* Length of queue Q.  */
00076 #define QUEUE_length(TYPE, Q) queue_ ## TYPE ## _length (Q)
00077 
00078 /* Free queue Q.  Q's free_func is called once for each element.  */
00079 #define QUEUE_free(TYPE, Q) queue_ ## TYPE ## _free (Q)
00080 
00081 /* Iterate over elements in the queue Q and call function OPERATE on
00082    each element.  It is allowed to remove element by OPERATE.  OPERATE
00083    returns false to terminate the iteration and true to continue the
00084    iteration.  Return false if iteration is terminated by function
00085    OPERATE, otherwise return true.  */
00086 #define QUEUE_iterate(TYPE, Q, OPERATE, PARAM)  \
00087   queue_ ## TYPE ## _iterate ((Q), (OPERATE), (PARAM))
00088 
00089 /* Remove the element per the state of iterator ITER from queue Q.
00090    Leave the caller to release the data in the queue element.  */
00091 #define QUEUE_remove_elem(TYPE, Q, ITER) \
00092   queue_ ## TYPE ## _remove_elem ((Q), (ITER))
00093 
00094 /* Define a new queue implementation.  */
00095 
00096 #define QUEUE(TYPE) struct queue_ ## TYPE
00097 #define QUEUE_ELEM(TYPE) struct queue_elem_ ## TYPE
00098 #define QUEUE_ITER(TYPE) struct queue_iter_ ## TYPE
00099 #define QUEUE_ITER_FUNC(TYPE) queue_ ## TYPE ## _operate_func
00100 
00101 #define DEFINE_QUEUE_P(TYPE)                    \
00102 QUEUE_ELEM (TYPE)                               \
00103 {                                               \
00104   QUEUE_ELEM (TYPE) *next;                      \
00105                                                 \
00106   TYPE data;                                    \
00107 };                                              \
00108                                                 \
00109 /* Queue iterator.  */                          \
00110 QUEUE_ITER (TYPE)                               \
00111 {                                               \
00112   /* The current element during traverse.  */   \
00113   QUEUE_ELEM (TYPE) *p;                 \
00114   /* The previous element of P.  */             \
00115   QUEUE_ELEM (TYPE) *prev;                      \
00116 };                                              \
00117                                                 \
00118 QUEUE(TYPE)                                     \
00119 {                                               \
00120   /*  The head and tail of the queue.  */       \
00121   QUEUE_ELEM (TYPE) *head;                      \
00122   QUEUE_ELEM (TYPE) *tail;                      \
00123   /* Function to release the data put in each   \
00124      queue element.  */                 \
00125   void (*free_func) (TYPE);                     \
00126 };                                              \
00127                                                 \
00128 void                                                                    \
00129 queue_ ## TYPE ## _enque (QUEUE (TYPE) *q, TYPE v)                      \
00130 {                                                                       \
00131   QUEUE_ELEM (TYPE) *p                                                  \
00132     = xmalloc (sizeof (QUEUE_ELEM (TYPE)));                             \
00133                                                                         \
00134   gdb_assert (q != NULL);                                               \
00135   p->data = v;                                                          \
00136   p->next = NULL;                                                       \
00137   if (q->tail == NULL)                                                  \
00138     {                                                                   \
00139       q->tail = p;                                                      \
00140       q->head = p;                                                      \
00141     }                                                                   \
00142   else                                                                  \
00143     {                                                                   \
00144       q->tail->next = p;                                                \
00145       q->tail = p;                                                      \
00146     }                                                                   \
00147 }                                                                       \
00148                                                                         \
00149 TYPE                                                                    \
00150 queue_ ## TYPE ## _deque (QUEUE (TYPE) *q)                              \
00151 {                                                                       \
00152   QUEUE_ELEM (TYPE) *p;                                         \
00153   TYPE v;                                                               \
00154                                                                         \
00155   gdb_assert (q != NULL);                                               \
00156   p = q->head;                                                          \
00157   gdb_assert (p != NULL);                                               \
00158                                                                         \
00159   if (q->head == q->tail)                                               \
00160     {                                                                   \
00161       q->head = NULL;                                                   \
00162       q->tail = NULL;                                                   \
00163     }                                                                   \
00164   else                                                                  \
00165     q->head = q->head->next;                                            \
00166                                                                         \
00167   v = p->data;                                                          \
00168                                                                         \
00169   xfree (p);                                                            \
00170   return v;                                                             \
00171 }                                                                       \
00172                                                                         \
00173 TYPE                                                                    \
00174 queue_ ## TYPE ## _peek (QUEUE (TYPE) *q)                               \
00175 {                                                                       \
00176   gdb_assert (q != NULL);                                               \
00177   gdb_assert (q->head != NULL);                                 \
00178   return q->head->data;                                         \
00179 }                                                                       \
00180                                                                         \
00181 int                                                                     \
00182 queue_ ## TYPE ## _is_empty (QUEUE (TYPE) *q)                           \
00183 {                                                                       \
00184   gdb_assert (q != NULL);                                               \
00185   return q->head == NULL;                                               \
00186 }                                                                       \
00187                                                                         \
00188 void                                                                    \
00189 queue_ ## TYPE ## _remove_elem (QUEUE (TYPE) *q,                        \
00190                                 QUEUE_ITER (TYPE) *iter)                \
00191 {                                                                       \
00192   gdb_assert (q != NULL);                                               \
00193   gdb_assert (iter != NULL && iter->p != NULL);                 \
00194                                                                         \
00195   if (iter->p == q->head || iter->p == q->tail)                 \
00196     {                                                                   \
00197       if (iter->p == q->head)                                           \
00198         q->head = iter->p->next;                                        \
00199       if (iter->p == q->tail)                                           \
00200         q->tail = iter->prev;                                           \
00201     }                                                                   \
00202   else                                                                  \
00203     iter->prev->next = iter->p->next;                                   \
00204                                                                         \
00205   xfree (iter->p);                                                      \
00206   /* Indicate that ITER->p has been deleted from QUEUE q.  */           \
00207   iter->p = NULL;                                                       \
00208 }                                                                       \
00209                                                                         \
00210 int                                                                     \
00211 queue_ ## TYPE ## _iterate (QUEUE (TYPE) *q,                            \
00212                             QUEUE_ITER_FUNC (TYPE) operate,             \
00213                             void *data)                         \
00214 {                                                                       \
00215   QUEUE_ELEM (TYPE) *next = NULL;                                       \
00216   QUEUE_ITER (TYPE) iter = { NULL, NULL };                              \
00217                                                                         \
00218   gdb_assert (q != NULL);                                               \
00219                                                                         \
00220   for (iter.p = q->head; iter.p != NULL; iter.p = next)         \
00221     {                                                                   \
00222       next = iter.p->next;                                              \
00223       if (!operate (q, &iter, iter.p->data, data))                      \
00224         return 0;                                                       \
00225       /* ITER.P was not deleted by function OPERATE.  */                \
00226       if (iter.p != NULL)                                               \
00227         iter.prev = iter.p;                                             \
00228     }                                                                   \
00229   return 1;                                                             \
00230 }                                                                       \
00231                                                                         \
00232 QUEUE (TYPE) *                                                          \
00233 queue_ ## TYPE ## _alloc (void (*free_func) (TYPE))                     \
00234 {                                                                       \
00235   QUEUE (TYPE) *q;                                                      \
00236                                                                         \
00237   q = (QUEUE (TYPE) *) xmalloc (sizeof (QUEUE (TYPE)));         \
00238   q->head = NULL;                                                       \
00239   q->tail = NULL;                                                       \
00240   q->free_func = free_func;                                             \
00241   return q;                                                             \
00242 }                                                                       \
00243                                                                         \
00244 int                                                                     \
00245 queue_ ## TYPE ## _length (QUEUE (TYPE) *q)                             \
00246 {                                                                       \
00247   QUEUE_ELEM (TYPE) *p;                                         \
00248   int len = 0;                                                          \
00249                                                                         \
00250   gdb_assert (q != NULL);                                               \
00251                                                                         \
00252   for (p = q->head; p != NULL; p = p->next)                             \
00253     len++;                                                              \
00254                                                                         \
00255   return len;                                                           \
00256 }                                                                       \
00257                                                                         \
00258 void                                                                    \
00259 queue_ ## TYPE ## _free (QUEUE (TYPE) *q)                               \
00260 {                                                                       \
00261   QUEUE_ELEM (TYPE) *p, *next;                                          \
00262                                                                         \
00263   gdb_assert (q != NULL);                                               \
00264                                                                         \
00265   for (p = q->head; p != NULL; p = next)                                \
00266     {                                                                   \
00267       next = p->next;                                                   \
00268       if (q->free_func)                                         \
00269         q->free_func (p->data);                                 \
00270       xfree (p);                                                        \
00271     }                                                                   \
00272   xfree (q);                                                            \
00273 }                                                                       \
00274 
00275 /* External declarations for queue functions.  */
00276 #define DECLARE_QUEUE_P(TYPE)                                   \
00277 QUEUE (TYPE);                                                   \
00278 QUEUE_ELEM (TYPE);                                              \
00279 QUEUE_ITER (TYPE);                                              \
00280 extern void                                                     \
00281   queue_ ## TYPE ## _enque (QUEUE (TYPE) *q, TYPE v);           \
00282 extern TYPE                                                     \
00283   queue_ ## TYPE ## _deque (QUEUE (TYPE) *q);                   \
00284 extern int queue_ ## TYPE ## _is_empty (QUEUE (TYPE) *q);       \
00285 extern QUEUE (TYPE) *                                           \
00286   queue_ ## TYPE ## _alloc (void (*free_func) (TYPE));          \
00287 extern int queue_ ## TYPE ## _length (QUEUE (TYPE) *q); \
00288 extern TYPE                                                     \
00289   queue_ ## TYPE ## _peek (QUEUE (TYPE) *q);                    \
00290 extern void queue_ ## TYPE ## _free (QUEUE (TYPE) *q);          \
00291 typedef int QUEUE_ITER_FUNC(TYPE) (QUEUE (TYPE) *,              \
00292                                    QUEUE_ITER (TYPE) *, \
00293                                    TYPE,                        \
00294                                    void *);                     \
00295 extern int                                                      \
00296   queue_ ## TYPE ## _iterate (QUEUE (TYPE) *q,                  \
00297                               QUEUE_ITER_FUNC (TYPE) operate,   \
00298                               void *);                          \
00299 extern void                                                     \
00300   queue_ ## TYPE ## _remove_elem (QUEUE (TYPE) *q,              \
00301                                   QUEUE_ITER (TYPE) *iter);     \
00302 
00303 #endif /* QUEUE_H */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines