00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef _XENO_NUCLEUS_BHEAP_H
00021 #define _XENO_NUCLEUS_BHEAP_H
00022
00023 #include <nucleus/compiler.h>
00024
00025
00026 #include <nucleus/assert.h>
00027
00028
00029
00030 typedef unsigned long long bheap_key_t;
00031
00032 typedef struct bheaph {
00033 bheap_key_t key;
00034 unsigned prio;
00035 unsigned pos;
00036 } bheaph_t;
00037
00038 #define bheaph_init(holder) do { } while (0)
00039 #define bheaph_key(holder) ((holder)->key)
00040 #define bheaph_prio(holder) ((holder)->prio)
00041 #define bheaph_pos(holder) ((holder)->pos)
00042 #define bheaph_lt(h1, h2) ((long long) ((h1)->key - (h2)->key) < 0 || \
00043 ((h1)->key == (h2)->key && \
00044 (h1)->prio > (h2)->prio))
00045
00046 typedef struct bheap {
00047 unsigned sz;
00048 unsigned last;
00049 bheaph_t *elems[1];
00050 } bheap_t;
00051
00052 #define DECLARE_BHEAP_CONTAINER(name, sz) \
00053 struct { \
00054 bheap_t bheap; \
00055 bheaph_t *elems[sz]; \
00056 } name
00057
00058
00059 static inline int bheap_ordered(bheap_t *heap)
00060 {
00061 unsigned i;
00062 for (i = 2; i < heap->last; i++)
00063 if (bheaph_lt(heap->elems[i], heap->elems[i / 2]))
00064 return 0;
00065 return 1;
00066 }
00067
00068 #define BHEAP_CHECK(heap) \
00069 XENO_BUGON(QUEUES, ((heap)->sz == 0) || !bheap_ordered(heap))
00070
00071 #define bheap_gethead(heap) \
00072 ({ \
00073 bheap_t *_bheap = &(heap)->bheap; \
00074 BHEAP_CHECK(_bheap); \
00075 __internal_bheap_gethead(_bheap); \
00076 })
00077
00078 static inline bheaph_t *__internal_bheap_gethead(bheap_t *heap)
00079 {
00080 if (heap->last == 1)
00081 return NULL;
00082
00083 return heap->elems[1];
00084 }
00085
00086 #define bheap_next(heap, holder) \
00087 ({ \
00088 bheap_t *_bheap = &(heap)->bheap; \
00089 BHEAP_CHECK(_bheap); \
00090 __internal_bheap_next(_bheap, holder); \
00091 })
00092
00093 static inline bheaph_t *__internal_bheap_next(bheap_t *heap, bheaph_t *holder)
00094 {
00095 unsigned pos;
00096
00097 if (unlikely(bheaph_pos(holder) >= heap->last
00098 || heap->elems[bheaph_pos(holder)] != holder))
00099 return (bheaph_t *) ERR_PTR(-EINVAL);
00100
00101 pos = bheaph_pos(holder) + 1;
00102
00103 return likely(pos < heap->last) ? heap->elems[pos] : NULL;
00104 }
00105
00106 static inline bheaph_t *bheaph_parent(bheap_t *heap, bheaph_t *holder)
00107 {
00108 const unsigned pos = holder->pos;
00109
00110 return likely(pos > 1) ? heap->elems[pos / 2] : NULL;
00111 }
00112
00113 static inline bheaph_t *bheaph_child(bheap_t *heap, bheaph_t *holder, int side)
00114 {
00115 const unsigned pos = 2 * holder->pos + side;
00116
00117 return likely(pos < heap->last) ? heap->elems[pos] : NULL;
00118 }
00119
00120 #define bheap_init(heap, sz) __internal_bheap_init(&(heap)->bheap, sz)
00121
00122 static inline void __internal_bheap_init(bheap_t *heap, unsigned sz)
00123 {
00124 heap->sz = sz;
00125 heap->last = 1;
00126 }
00127
00128 #define bheap_destroy(heap) __internal_bheap_destroy(&(heap)->bheap)
00129
00130 static inline void __internal_bheap_destroy(bheap_t *heap)
00131 {
00132 heap->sz = 0;
00133 heap->last = 1;
00134 }
00135
00136 static inline void bheap_swap(bheap_t *heap, bheaph_t *h1, bheaph_t *h2)
00137 {
00138 const unsigned pos2 = bheaph_pos(h2);
00139
00140 heap->elems[bheaph_pos(h1)] = h2;
00141 bheaph_pos(h2) = bheaph_pos(h1);
00142 heap->elems[pos2] = h1;
00143 bheaph_pos(h1) = pos2;
00144 }
00145
00146 static inline void bheap_up(bheap_t *heap, bheaph_t *holder)
00147 {
00148 bheaph_t *parent;
00149
00150 while ((parent = bheaph_parent(heap, holder)) && bheaph_lt(holder, parent))
00151 bheap_swap(heap, holder, parent);
00152 }
00153
00154 static inline void bheap_down(bheap_t *heap, bheaph_t *holder)
00155 {
00156 bheaph_t *left, *right, *minchild;
00157
00158 for (;;) {
00159 left = bheaph_child(heap, holder, 0);
00160 right = bheaph_child(heap, holder, 1);
00161
00162 if (left && right)
00163 minchild = bheaph_lt(left, right) ? left : right;
00164 else
00165 minchild = left ?: right;
00166
00167 if (!minchild || bheaph_lt(holder, minchild))
00168 break;
00169
00170 bheap_swap(heap, minchild, holder);
00171 }
00172 }
00173
00174 #define bheap_insert(heap, holder) \
00175 ({ \
00176 bheap_t *_bheap = &(heap)->bheap; \
00177 BHEAP_CHECK(_bheap); \
00178 __internal_bheap_insert(_bheap, holder); \
00179 })
00180
00181 static inline int __internal_bheap_insert(bheap_t *heap, bheaph_t *holder)
00182 {
00183 if (heap->last == heap->sz + 1)
00184 return EBUSY;
00185
00186 heap->elems[heap->last] = holder;
00187 bheaph_pos(holder) = heap->last;
00188 ++heap->last;
00189 bheap_up(heap, holder);
00190 return 0;
00191 }
00192
00193 #define bheap_delete(heap, holder) \
00194 ({ \
00195 bheap_t *_bheap = &(heap)->bheap; \
00196 BHEAP_CHECK(_bheap); \
00197 __internal_bheap_delete(_bheap, holder); \
00198 })
00199
00200 static inline int __internal_bheap_delete(bheap_t *heap, bheaph_t *holder)
00201 {
00202 bheaph_t *lasth;
00203
00204 if (unlikely(bheaph_pos(holder) >= heap->last
00205 || heap->elems[bheaph_pos(holder)] != holder))
00206 return EINVAL;
00207
00208 --heap->last;
00209 if (heap->last != bheaph_pos(holder)) {
00210 bheaph_t *parent;
00211 lasth = heap->elems[heap->last];
00212 heap->elems[bheaph_pos(holder)] = lasth;
00213 bheaph_pos(lasth) = bheaph_pos(holder);
00214 if ((parent = bheaph_parent(heap, lasth)) && bheaph_lt(lasth, parent))
00215 bheap_up(heap, lasth);
00216 else
00217 bheap_down(heap, lasth);
00218 }
00219
00220 return 0;
00221 }
00222
00223 #define bheap_get(heap) \
00224 ({ \
00225 bheap_t *_bheap = &(heap)->bheap; \
00226 BHEAP_CHECK(_bheap); \
00227 __internal_bheap_get(_bheap, holder); \
00228 })
00229
00230 static inline bheaph_t *__internal_bheap_get(bheap_t *heap)
00231 {
00232 bheaph_t *holder = __internal_bheap_gethead(heap);
00233
00234 if (!holder)
00235 return NULL;
00236
00237 __internal_bheap_delete(heap, holder);
00238
00239 return holder;
00240 }
00241
00242 #endif