pheap.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _PICO_UTIL_PHEAP_H
8 #define _PICO_UTIL_PHEAP_H
9 
10 #include "pico.h"
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 // PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PHEAP, Enable/disable assertions in the pheap module, type=bool, default=0, group=pico_util
17 #ifndef PARAM_ASSERTIONS_ENABLED_PHEAP
18 #define PARAM_ASSERTIONS_ENABLED_PHEAP 0
19 #endif
20 
37 // PICO_CONFIG: PICO_PHEAP_MAX_ENTRIES, Maximum number of entries in the pheap, min=1, max=65534, default=255, group=pico_util
38 #ifndef PICO_PHEAP_MAX_ENTRIES
39 #define PICO_PHEAP_MAX_ENTRIES 255
40 #endif
41 
42 // public heap_node ids are numbered from 1 (0 means none)
43 #if PICO_PHEAP_MAX_ENTRIES < 256
44 typedef uint8_t pheap_node_id_t;
45 #elif PICO_PHEAP_MAX_ENTRIES < 65535
46 typedef uint16_t pheap_node_id_t;
47 #else
48 #error invalid PICO_PHEAP_MAX_ENTRIES
49 #endif
50 
51 typedef struct pheap_node {
52  pheap_node_id_t child, sibling, parent;
53 } pheap_node_t;
54 
60 typedef bool (*pheap_comparator)(void *user_data, pheap_node_id_t a, pheap_node_id_t b);
61 
62 typedef struct pheap {
63  pheap_node_t *nodes;
64  pheap_comparator comparator;
65  void *user_data;
66  pheap_node_id_t max_nodes;
67  pheap_node_id_t root_id;
68  // we remove from head and add to tail to stop reusing the same ids
69  pheap_node_id_t free_head_id;
70  pheap_node_id_t free_tail_id;
71 } pheap_t;
72 
86 pheap_t *ph_create(uint max_nodes, pheap_comparator comparator, void *user_data);
87 
92 void ph_clear(pheap_t *heap);
93 
100 void ph_destroy(pheap_t *heap);
101 
102 // internal method
103 static inline pheap_node_t *ph_get_node(pheap_t *heap, pheap_node_id_t id) {
104  assert(id && id <= heap->max_nodes);
105  return heap->nodes + id - 1;
106 }
107 
108 // internal method
109 static void ph_add_child_node(pheap_t *heap, pheap_node_id_t parent_id, pheap_node_id_t child_id) {
110  pheap_node_t *n = ph_get_node(heap, parent_id);
111  assert(parent_id);
112  assert(child_id);
113  assert(parent_id != child_id);
114  pheap_node_t *c = ph_get_node(heap, child_id);
115  c->parent = parent_id;
116  if (!n->child) {
117  n->child = child_id;
118  } else {
119  c->sibling = n->child;
120  n->child = child_id;
121  }
122 }
123 
124 // internal method
125 static pheap_node_id_t ph_merge_nodes(pheap_t *heap, pheap_node_id_t a, pheap_node_id_t b) {
126  if (!a) return b;
127  if (!b) return a;
128  if (heap->comparator(heap->user_data, a, b)) {
129  ph_add_child_node(heap, a, b);
130  return a;
131  } else {
132  ph_add_child_node(heap, b, a);
133  return b;
134  }
135 }
136 
143 static inline pheap_node_id_t ph_new_node(pheap_t *heap) {
144  if (!heap->free_head_id) return 0;
145  pheap_node_id_t id = heap->free_head_id;
146  pheap_node_t *hn = ph_get_node(heap, id);
147  heap->free_head_id = hn->sibling;
148  if (!heap->free_head_id) heap->free_tail_id = 0;
149  hn->child = hn->sibling = hn->parent = 0;
150  return id;
151 }
152 
164 static inline pheap_node_id_t ph_insert_node(pheap_t *heap, pheap_node_id_t id) {
165  assert(id);
166  pheap_node_t *hn = ph_get_node(heap, id);
167  hn->child = hn->sibling = hn->parent = 0;
168  heap->root_id = ph_merge_nodes(heap, heap->root_id, id);
169  return heap->root_id;
170 }
171 
179 static inline pheap_node_id_t ph_peek_head(pheap_t *heap) {
180  return heap->root_id;
181 }
182 
198 pheap_node_id_t ph_remove_head(pheap_t *heap, bool free);
199 
212 static inline pheap_node_id_t ph_remove_and_free_head(pheap_t *heap) {
213  return ph_remove_head(heap, true);
214 }
215 
224 bool ph_remove_and_free_node(pheap_t *heap, pheap_node_id_t id);
225 
234 static inline bool ph_contains_node(pheap_t *heap, pheap_node_id_t id) {
235  return id == heap->root_id || ph_get_node(heap, id)->parent;
236 }
237 
238 
245 static inline void ph_free_node(pheap_t *heap, pheap_node_id_t id) {
246  assert(id && !ph_contains_node(heap, id));
247  if (heap->free_tail_id) {
248  ph_get_node(heap, heap->free_tail_id)->sibling = id;
249  }
250  if (!heap->free_head_id) {
251  assert(!heap->free_tail_id);
252  heap->free_head_id = id;
253  }
254  heap->free_tail_id = id;
255 }
256 
264 void ph_dump(pheap_t *heap, void (*dump_key)(pheap_node_id_t id, void *user_data), void *user_data);
265 
275 void ph_post_alloc_init(pheap_t *heap, uint max_nodes, pheap_comparator comparator, void *user_data);
276 
281 #define PHEAP_DEFINE_STATIC(name, _max_nodes) \
282  static_assert(_max_nodes && _max_nodes < (1u << (8 * sizeof(pheap_node_id_t))), ""); \
283  static pheap_node_t name ## _nodes[_max_nodes]; \
284  static pheap_t name = { \
285  .nodes = name ## _nodes, \
286  .max_nodes = _max_nodes \
287  };
288 
289 
290 #ifdef __cplusplus
291 }
292 #endif
293 
294 #endif
bool(* pheap_comparator)(void *user_data, pheap_node_id_t a, pheap_node_id_t b)
Definition: pheap.h:60
void ph_destroy(pheap_t *heap)
Definition: pheap.c:37
static void ph_free_node(pheap_t *heap, pheap_node_id_t id)
Definition: pheap.h:245
void ph_clear(pheap_t *heap)
Definition: pheap.c:27
void ph_post_alloc_init(pheap_t *heap, uint max_nodes, pheap_comparator comparator, void *user_data)
Definition: pheap.c:19
static bool ph_contains_node(pheap_t *heap, pheap_node_id_t id)
Definition: pheap.h:234
bool ph_remove_and_free_node(pheap_t *heap, pheap_node_id_t id)
Definition: pheap.c:82
pheap_node_id_t ph_remove_head(pheap_t *heap, bool free)
Definition: pheap.c:76
static pheap_node_id_t ph_peek_head(pheap_t *heap)
Definition: pheap.h:179
void ph_dump(pheap_t *heap, void(*dump_key)(pheap_node_id_t id, void *user_data), void *user_data)
static pheap_node_id_t ph_insert_node(pheap_t *heap, pheap_node_id_t id)
Definition: pheap.h:164
pheap_t * ph_create(uint max_nodes, pheap_comparator comparator, void *user_data)
Definition: pheap.c:11
static pheap_node_id_t ph_remove_and_free_head(pheap_t *heap)
Definition: pheap.h:212
static pheap_node_id_t ph_new_node(pheap_t *heap)
Definition: pheap.h:143
Definition: pheap.h:51
Definition: pheap.h:62