Loading...
Searching...
No Matches
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
13extern "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
44typedef uint8_t pheap_node_id_t;
45#elif PICO_PHEAP_MAX_ENTRIES < 65535
46typedef uint16_t pheap_node_id_t;
47#else
48#error invalid PICO_PHEAP_MAX_ENTRIES
49#endif
50
57typedef struct pheap_node {
58 pheap_node_id_t child;
59 pheap_node_id_t sibling;
60 pheap_node_id_t parent;
62
69typedef bool (*pheap_comparator)(void *user_data, pheap_node_id_t a, pheap_node_id_t b);
70
77typedef struct pheap {
80 void *user_data;
81 pheap_node_id_t max_nodes;
82 pheap_node_id_t root_id;
83 // we remove from head and add to tail to stop reusing the same ids
84 pheap_node_id_t free_head_id;
85 pheap_node_id_t free_tail_id;
87
102pheap_t *ph_create(uint max_nodes, pheap_comparator comparator, void *user_data);
103
109void ph_clear(pheap_t *heap);
110
118void ph_destroy(pheap_t *heap);
119
120// internal method
121static inline pheap_node_t *ph_get_node(pheap_t *heap, pheap_node_id_t id) {
122 assert(id && id <= heap->max_nodes);
123 return heap->nodes + id - 1;
124}
125
126// internal method
127static void ph_add_child_node(pheap_t *heap, pheap_node_id_t parent_id, pheap_node_id_t child_id) {
128 pheap_node_t *n = ph_get_node(heap, parent_id);
129 assert(parent_id);
130 assert(child_id);
131 assert(parent_id != child_id);
132 pheap_node_t *c = ph_get_node(heap, child_id);
133 c->parent = parent_id;
134 if (!n->child) {
135 n->child = child_id;
136 } else {
137 c->sibling = n->child;
138 n->child = child_id;
139 }
140}
141
142// internal method
143static pheap_node_id_t ph_merge_nodes(pheap_t *heap, pheap_node_id_t a, pheap_node_id_t b) {
144 if (!a) return b;
145 if (!b) return a;
146 if (heap->comparator(heap->user_data, a, b)) {
147 ph_add_child_node(heap, a, b);
148 return a;
149 } else {
150 ph_add_child_node(heap, b, a);
151 return b;
152 }
153}
154
162static inline pheap_node_id_t ph_new_node(pheap_t *heap) {
163 if (!heap->free_head_id) return 0;
164 pheap_node_id_t id = heap->free_head_id;
165 pheap_node_t *hn = ph_get_node(heap, id);
166 heap->free_head_id = hn->sibling;
167 if (!heap->free_head_id) heap->free_tail_id = 0;
168 hn->child = hn->sibling = hn->parent = 0;
169 return id;
170}
171
184static inline pheap_node_id_t ph_insert_node(pheap_t *heap, pheap_node_id_t id) {
185 assert(id);
186 pheap_node_t *hn = ph_get_node(heap, id);
187 hn->child = hn->sibling = hn->parent = 0;
188 heap->root_id = ph_merge_nodes(heap, heap->root_id, id);
189 return heap->root_id;
190}
191
200static inline pheap_node_id_t ph_peek_head(pheap_t *heap) {
201 return heap->root_id;
202}
203
220pheap_node_id_t ph_remove_head(pheap_t *heap, bool free);
221
235static inline pheap_node_id_t ph_remove_and_free_head(pheap_t *heap) {
236 return ph_remove_head(heap, true);
237}
238
248bool ph_remove_and_free_node(pheap_t *heap, pheap_node_id_t id);
249
259static inline bool ph_contains_node(pheap_t *heap, pheap_node_id_t id) {
260 return id == heap->root_id || ph_get_node(heap, id)->parent;
261}
262
263
271static inline void ph_free_node(pheap_t *heap, pheap_node_id_t id) {
272 assert(id && !ph_contains_node(heap, id));
273 if (heap->free_tail_id) {
274 ph_get_node(heap, heap->free_tail_id)->sibling = id;
275 }
276 if (!heap->free_head_id) {
277 assert(!heap->free_tail_id);
278 heap->free_head_id = id;
279 }
280 heap->free_tail_id = id;
281}
282
291void ph_dump(pheap_t *heap, void (*dump_key)(pheap_node_id_t id, void *user_data), void *user_data);
292
303void ph_post_alloc_init(pheap_t *heap, uint max_nodes, pheap_comparator comparator, void *user_data);
304
310#define PHEAP_DEFINE_STATIC(name, _max_nodes) \
311 static_assert(_max_nodes && _max_nodes < (1u << (8 * sizeof(pheap_node_id_t))), ""); \
312 static pheap_node_t name ## _nodes[_max_nodes]; \
313 static pheap_t name = { \
314 .nodes = name ## _nodes, \
315 .max_nodes = _max_nodes \
316 };
317
318
319#ifdef __cplusplus
320}
321#endif
322
323#endif
bool(* pheap_comparator)(void *user_data, pheap_node_id_t a, pheap_node_id_t b)
A user comparator function for nodes in a pairing heap.
Definition pheap.h:69
struct pheap pheap_t
A pairing heap instance.
void ph_destroy(pheap_t *heap)
De-allocates a pairing heap.
Definition pheap.c:37
static void ph_free_node(pheap_t *heap, pheap_node_id_t id)
Free a node that is not currently in the heap, but has been allocated.
Definition pheap.h:271
void ph_clear(pheap_t *heap)
Removes all nodes from the pairing heap.
Definition pheap.c:27
struct pheap_node pheap_node_t
A node within a pairing heap.
void ph_post_alloc_init(pheap_t *heap, uint max_nodes, pheap_comparator comparator, void *user_data)
Initialize a statically allocated heap (ph_create() using the C heap). The heap member nodes must be ...
Definition pheap.c:19
static bool ph_contains_node(pheap_t *heap, pheap_node_id_t id)
Determine if the heap contains a given node. Note containment refers to whether the node is inserted ...
Definition pheap.h:259
bool ph_remove_and_free_node(pheap_t *heap, pheap_node_id_t id)
Remove and free an arbitrary node from the pairing heap. This is a more costly operation than removin...
Definition pheap.c:82
pheap_node_id_t ph_remove_head(pheap_t *heap, bool free)
Remove the head node from the pairing heap. This head node is the node which compares first in the lo...
Definition pheap.c:76
static pheap_node_id_t ph_peek_head(pheap_t *heap)
Returns the head node in the heap, i.e. the node which compares first, but without removing it from t...
Definition pheap.h:200
void ph_dump(pheap_t *heap, void(*dump_key)(pheap_node_id_t id, void *user_data), void *user_data)
Print a representation of the heap for debugging.
Definition pheap.c:135
static pheap_node_id_t ph_insert_node(pheap_t *heap, pheap_node_id_t id)
Inserts a node into the heap.
Definition pheap.h:184
pheap_t * ph_create(uint max_nodes, pheap_comparator comparator, void *user_data)
Create a pairing heap, which effectively maintains an efficient sorted ordering of nodes....
Definition pheap.c:11
static pheap_node_id_t ph_remove_and_free_head(pheap_t *heap)
Remove the head node from the pairing heap. This head node is the node which compares first in the lo...
Definition pheap.h:235
static pheap_node_id_t ph_new_node(pheap_t *heap)
Allocate a new node from the unused space in the heap.
Definition pheap.h:162
A node within a pairing heap.
Definition pheap.h:57
pheap_node_id_t sibling
Id of the next sibling node, or 0 if none.
Definition pheap.h:59
pheap_node_id_t child
Id of the first child node, or 0 if none.
Definition pheap.h:58
pheap_node_id_t parent
Id of the parent node, or 0 if this is the root.
Definition pheap.h:60
A pairing heap instance.
Definition pheap.h:77
pheap_node_id_t free_tail_id
Id of the last node in the free list, or 0 if none.
Definition pheap.h:85
pheap_comparator comparator
Comparator used to determine relative ordering of nodes.
Definition pheap.h:79
pheap_node_id_t max_nodes
Maximum number of nodes the heap can hold.
Definition pheap.h:81
pheap_node_id_t root_id
Id of the current root (minimum) node, or 0 if the heap is empty.
Definition pheap.h:82
pheap_node_id_t free_head_id
Id of the first node in the free list, or 0 if none.
Definition pheap.h:84
pheap_node_t * nodes
Array of all nodes, indexed by node id minus one.
Definition pheap.h:78
void * user_data
User data pointer passed to the comparator.
Definition pheap.h:80