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 #define BHEAP_CHECK(heap)   XENO_BUGON(QUEUES, ((heap)->sz == 0))
00063 
00064 #define bheap_gethead(heap)                     \
00065 ({                                              \
00066     bheap_t *_bheap = &(heap)->bheap;           \
00067     BHEAP_CHECK(_bheap);                        \
00068     __internal_bheap_gethead(_bheap);           \
00069 })
00070 
00071 static inline bheaph_t *__internal_bheap_gethead(bheap_t *heap)
00072 {
00073     if (heap->last == 1)
00074         return NULL;
00075 
00076     return heap->elems[1];
00077 }
00078 
00079 static inline bheaph_t *bheaph_parent(bheap_t *heap, bheaph_t *holder)
00080 {
00081     const unsigned pos = holder->pos;
00082 
00083     return likely(pos > 1) ? heap->elems[pos / 2] : NULL;
00084 }
00085 
00086 static inline bheaph_t *bheaph_child(bheap_t *heap, bheaph_t *holder, int side)
00087 {
00088     const unsigned pos = 2 * holder->pos + side;
00089 
00090     return likely(pos < heap->last) ? heap->elems[pos] : NULL;
00091 }
00092 
00093 #define bheap_init(heap, sz) __internal_bheap_init(&(heap)->bheap, sz)
00094 
00095 static inline void __internal_bheap_init(bheap_t *heap, unsigned sz)
00096 {
00097     heap->sz = sz;
00098     heap->last = 1;
00099 }
00100 
00101 #define bheap_destroy(heap) __internal_bheap_destroy(&(heap)->bheap)
00102 
00103 static inline void __internal_bheap_destroy(bheap_t *heap)
00104 {
00105     heap->sz = 0;
00106     heap->last = 1;
00107 }
00108 
00109 static inline void bheap_swap(bheap_t *heap, bheaph_t *h1, bheaph_t *h2)
00110 {
00111     const unsigned pos2 = bheaph_pos(h2);
00112 
00113     heap->elems[bheaph_pos(h1)] = h2;
00114     bheaph_pos(h2) = bheaph_pos(h1);
00115     heap->elems[pos2] = h1;
00116     bheaph_pos(h1) = pos2;
00117 }
00118 
00119 static inline void bheap_up(bheap_t *heap, bheaph_t *holder)
00120 {
00121     bheaph_t *parent;
00122 
00123     while ((parent = bheaph_parent(heap, holder)) && bheaph_lt(holder, parent))
00124         bheap_swap(heap, holder, parent);
00125 }
00126 
00127 static inline void bheap_down(bheap_t *heap, bheaph_t *holder)
00128 {
00129     bheaph_t *left, *right, *minchild;
00130 
00131     for (;;) {
00132         left = bheaph_child(heap, holder, 0);
00133         right = bheaph_child(heap, holder, 1);
00134 
00135         if (left && right)
00136             minchild = bheaph_lt(left, right) ? left : right;
00137         else
00138             minchild = left ?: right;
00139 
00140         if (!minchild || bheaph_lt(holder, minchild))
00141             break;
00142 
00143         bheap_swap(heap, minchild, holder);
00144     }
00145 }
00146 
00147 #define bheap_insert(heap, holder)              \
00148 ({                                              \
00149     bheap_t *_bheap = &(heap)->bheap;           \
00150     BHEAP_CHECK(_bheap);                        \
00151     __internal_bheap_insert(_bheap, holder);    \
00152 })
00153 
00154 static inline int __internal_bheap_insert(bheap_t *heap, bheaph_t *holder)
00155 {
00156     if (heap->last == heap->sz + 1)
00157         return EBUSY;
00158 
00159     heap->elems[heap->last] = holder;
00160     bheaph_pos(holder) = heap->last;
00161     ++heap->last;
00162     bheap_up(heap, holder);
00163     return 0;
00164 }
00165 
00166 #define bheap_delete(heap, holder)              \
00167 ({                                              \
00168     bheap_t *_bheap = &(heap)->bheap;           \
00169     BHEAP_CHECK(_bheap);                        \
00170     __internal_bheap_delete(_bheap, holder);    \
00171 })
00172 
00173 static inline int __internal_bheap_delete(bheap_t *heap, bheaph_t *holder)
00174 {
00175     bheaph_t *lasth;
00176 
00177     if (bheaph_pos(holder) >= heap->last)
00178         return EINVAL;
00179 
00180     --heap->last;
00181     if (heap->last != bheaph_pos(holder)) {
00182         lasth = heap->elems[heap->last];
00183         heap->elems[bheaph_pos(holder)] = lasth;
00184         bheaph_pos(lasth) = bheaph_pos(holder);
00185         bheap_down(heap, lasth);
00186     }
00187 
00188     return 0;
00189 }
00190 
00191 #define bheap_get(heap)                         \
00192 ({                                              \
00193     bheap_t *_bheap = &(heap)->bheap;           \
00194     BHEAP_CHECK(_bheap);                        \
00195     __internal_bheap_get(_bheap, holder);       \
00196 })
00197 
00198 static inline bheaph_t *__internal_bheap_get(bheap_t *heap)
00199 {
00200     bheaph_t *holder = __internal_bheap_gethead(heap);
00201 
00202     if (!holder)
00203         return NULL;
00204 
00205     __internal_bheap_delete(heap, holder);
00206 
00207     return holder;
00208 }
00209 
00210 #endif /* _XENO_NUCLEUS_BHEAP_H */

Generated on Mon Dec 25 13:57:10 2006 for Xenomai API by  doxygen 1.4.6