include/nucleus/bheap.h

00001 /*
00002  * Copyright (C) 2006 Gilles Chanteperdrix <gilles.chanteperdrix@laposte.net>
00003  *
00004  * Xenomai is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published
00006  * by the Free Software Foundation; either version 2 of the License,
00007  * or (at your option) any later version.
00008  *
00009  * Xenomai is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with Xenomai; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00017  * 02111-1307, USA.
00018  */
00019 
00020 #ifndef _XENO_NUCLEUS_BHEAP_H
00021 #define _XENO_NUCLEUS_BHEAP_H
00022 
00023 #include <nucleus/compiler.h>
00024 
00025 /* debug support */
00026 #include <nucleus/assert.h>
00027 
00028 #ifndef CONFIG_XENO_OPT_DEBUG_QUEUES
00029 #define CONFIG_XENO_OPT_DEBUG_QUEUES 0
00030 #endif
00031 
00032 /* Priority queue implementation, using a binary heap. */
00033 
00034 typedef unsigned long long bheap_key_t;
00035 
00036 typedef struct bheaph {
00037     bheap_key_t key;
00038     unsigned prio;
00039     unsigned pos;
00040 } bheaph_t;
00041 
00042 #define bheaph_init(holder) do { } while (0)
00043 #define bheaph_key(holder)  ((holder)->key)
00044 #define bheaph_prio(holder) ((holder)->prio)
00045 #define bheaph_pos(holder)  ((holder)->pos)
00046 #define bheaph_lt(h1, h2)   ((h1)->key < (h2)->key ||     \
00047                              ((h1)->key == (h2)->key &&   \
00048                               (h1)->prio > (h2)->prio))
00049 
00050 typedef struct bheap {
00051     unsigned sz;
00052     unsigned last;
00053     bheaph_t *elems[1]; /* only padding, indexing starts at 1 */
00054 } bheap_t;
00055 
00056 #define DECLARE_BHEAP_CONTAINER(name, sz)       \
00057     struct {                                    \
00058         bheap_t bheap;                          \
00059         bheaph_t *elems[sz];                    \
00060     } name
00061 
00062 /* Check the binary heap invariant. */
00063 static inline int bheap_ordered(bheap_t *heap)
00064 {
00065         unsigned i;
00066         for (i = 2; i < heap->last; i++)
00067                 if (bheaph_lt(heap->elems[i], heap->elems[i / 2]))
00068                         return 0;
00069         return 1;
00070 }
00071 
00072 #define BHEAP_CHECK(heap) \
00073         XENO_BUGON(QUEUES, ((heap)->sz == 0) || !bheap_ordered(heap))
00074 
00075 #define bheap_gethead(heap)                     \
00076 ({                                              \
00077     bheap_t *_bheap = &(heap)->bheap;           \
00078     BHEAP_CHECK(_bheap);                        \
00079     __internal_bheap_gethead(_bheap);           \
00080 })
00081 
00082 static inline bheaph_t *__internal_bheap_gethead(bheap_t *heap)
00083 {
00084     if (heap->last == 1)
00085         return NULL;
00086 
00087     return heap->elems[1];
00088 }
00089 
00090 static inline bheaph_t *bheaph_parent(bheap_t *heap, bheaph_t *holder)
00091 {
00092     const unsigned pos = holder->pos;
00093 
00094     return likely(pos > 1) ? heap->elems[pos / 2] : NULL;
00095 }
00096 
00097 static inline bheaph_t *bheaph_child(bheap_t *heap, bheaph_t *holder, int side)
00098 {
00099     const unsigned pos = 2 * holder->pos + side;
00100 
00101     return likely(pos < heap->last) ? heap->elems[pos] : NULL;
00102 }
00103 
00104 #define bheap_init(heap, sz) __internal_bheap_init(&(heap)->bheap, sz)
00105 
00106 static inline void __internal_bheap_init(bheap_t *heap, unsigned sz)
00107 {
00108     heap->sz = sz;
00109     heap->last = 1;
00110 }
00111 
00112 #define bheap_destroy(heap) __internal_bheap_destroy(&(heap)->bheap)
00113 
00114 static inline void __internal_bheap_destroy(bheap_t *heap)
00115 {
00116     heap->sz = 0;
00117     heap->last = 1;
00118 }
00119 
00120 static inline void bheap_swap(bheap_t *heap, bheaph_t *h1, bheaph_t *h2)
00121 {
00122     const unsigned pos2 = bheaph_pos(h2);
00123 
00124     heap->elems[bheaph_pos(h1)] = h2;
00125     bheaph_pos(h2) = bheaph_pos(h1);
00126     heap->elems[pos2] = h1;
00127     bheaph_pos(h1) = pos2;
00128 }
00129 
00130 static inline void bheap_up(bheap_t *heap, bheaph_t *holder)
00131 {
00132     bheaph_t *parent;
00133 
00134     while ((parent = bheaph_parent(heap, holder)) && bheaph_lt(holder, parent))
00135         bheap_swap(heap, holder, parent);
00136 }
00137 
00138 static inline void bheap_down(bheap_t *heap, bheaph_t *holder)
00139 {
00140     bheaph_t *left, *right, *minchild;
00141 
00142     for (;;) {
00143         left = bheaph_child(heap, holder, 0);
00144         right = bheaph_child(heap, holder, 1);
00145 
00146         if (left && right)
00147             minchild = bheaph_lt(left, right) ? left : right;
00148         else
00149             minchild = left ?: right;
00150 
00151         if (!minchild || bheaph_lt(holder, minchild))
00152             break;
00153 
00154         bheap_swap(heap, minchild, holder);
00155     }
00156 }
00157 
00158 #define bheap_insert(heap, holder)              \
00159 ({                                              \
00160     bheap_t *_bheap = &(heap)->bheap;           \
00161     BHEAP_CHECK(_bheap);                        \
00162     __internal_bheap_insert(_bheap, holder);    \
00163 })
00164 
00165 static inline int __internal_bheap_insert(bheap_t *heap, bheaph_t *holder)
00166 {
00167     if (heap->last == heap->sz + 1)
00168         return EBUSY;
00169 
00170     heap->elems[heap->last] = holder;
00171     bheaph_pos(holder) = heap->last;
00172     ++heap->last;
00173     bheap_up(heap, holder);
00174     return 0;
00175 }
00176 
00177 #define bheap_delete(heap, holder)              \
00178 ({                                              \
00179     bheap_t *_bheap = &(heap)->bheap;           \
00180     BHEAP_CHECK(_bheap);                        \
00181     __internal_bheap_delete(_bheap, holder);    \
00182 })
00183 
00184 static inline int __internal_bheap_delete(bheap_t *heap, bheaph_t *holder)
00185 {
00186     bheaph_t *lasth;
00187 
00188     if (bheaph_pos(holder) >= heap->last)
00189         return EINVAL;
00190 
00191     --heap->last;
00192     if (heap->last != bheaph_pos(holder)) {
00193         bheaph_t *parent;
00194         lasth = heap->elems[heap->last];
00195         heap->elems[bheaph_pos(holder)] = lasth;
00196         bheaph_pos(lasth) = bheaph_pos(holder);
00197         if ((parent = bheaph_parent(heap, lasth)) && bheaph_lt(lasth, parent))
00198                 bheap_up(heap, lasth);
00199         else
00200                 bheap_down(heap, lasth);
00201     }
00202 
00203     return 0;
00204 }
00205 
00206 #define bheap_get(heap)                         \
00207 ({                                              \
00208     bheap_t *_bheap = &(heap)->bheap;           \
00209     BHEAP_CHECK(_bheap);                        \
00210     __internal_bheap_get(_bheap, holder);       \
00211 })
00212 
00213 static inline bheaph_t *__internal_bheap_get(bheap_t *heap)
00214 {
00215     bheaph_t *holder = __internal_bheap_gethead(heap);
00216 
00217     if (!holder)
00218         return NULL;
00219 
00220     __internal_bheap_delete(heap, holder);
00221 
00222     return holder;
00223 }
00224 
00225 #endif /* _XENO_NUCLEUS_BHEAP_H */

Generated on Sun Dec 9 10:37:17 2007 for Xenomai API by  doxygen 1.5.3