Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
pqmh.h
Go to the documentation of this file.
1/* -*- C -*-
2 * Serene programming language
3 * Copyright (C) 2019-2026 Sameer Rahmani <[email protected]>
4 *
5 * This library is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19#pragma once
20
21/** @file
22 A generic priority queue backed by a binary min-heap.
23
24 Elements are stored by pointer (`void *`), and the ordering is supplied through
25 a control vtable (`pqmh_control_t`), so the same heap serves any element type
26 -- the only thing that varies per type is the comparison. The element the
27 control orders first is the one at the root, returned by `pqmh_peek` and
28 removed by `pqmh_pop`. A "less" predicate that returns `a < b` yields a
29 min-heap, its inverse a max-heap.
30
31 This is a mutable, growable container. Its backing array is held in the manual
32 lifetime allocator
33 (`srn_mm_malloc`/`srn_mm_reallocate`/`srn_mm_free`) and grows by doubling, so a
34 `pqmh_t` must be released with `pqmh_free`. By convention the operations take a
35 `srn_context_t *` and reach the memory manager through `ctx->engine->mm`.
36
37 It is not synchronized; a `pqmh_t` is owned by a single thread and IS NOT
38 THREAD SAFE.
39*/
40
41#include <stddef.h>
42
43typedef struct srn_context_t srn_context_t;
44
45/**
46 * Strict weak ordering predicate over two elements. Returns true when `a`
47 * should leave the queue before `b` (for a min-heap, when `a < b`). `ctx` is
48 * the context handed to the operation, for comparators that need it.
49 */
50typedef bool (*pqmh_less_fn)(srn_context_t *ctx, const void *a, const void *b);
51
52/**
53 * Per type configuration. Only the comparison varies between element types. The
54 * heap operations themselves are type independent, so the control carries just
55 * the ordering predicate.
56 */
60
61/**
62 * A priority queue. `data` is the backing heap array of element pointers, `len`
63 * the live count, `cap` the allocated capacity. The control is bound at
64 * `pqmh_make` and not re-passed per operation.
65 */
66typedef struct pqmh_t {
68 void **data;
69 size_t len;
70 size_t cap;
72
73/**
74 * Create an empty queue ordered by `ctl`, with room for `initial_cap` elements
75 * (a small default is used when 0). The backing array comes from the manual
76 * allocator, so the queue must later be released with `pqmh_free`.
77 */
78[[nodiscard]] [[gnu::nonnull(1, 2)]]
79pqmh_t pqmh_make(srn_context_t *ctx, const pqmh_control_t *ctl, size_t initial_cap);
80
81/**
82 * Insert `elem`, growing the backing array (doubling) if it is full. Panics if
83 * the growth allocation fails.
84 */
85[[gnu::nonnull(1, 2)]]
86void pqmh_push(srn_context_t *ctx, pqmh_t *pq, void *elem);
87
88/**
89 * Remove the highest priority element into `*out` and return true, or return
90 * false (leaving `*out` untouched) when the queue is empty.
91 */
92[[nodiscard]] [[gnu::nonnull(1, 2, 3)]]
93bool pqmh_pop(srn_context_t *ctx, pqmh_t *pq, void **out);
94
95/**
96 * The highest priority element without removing it, or NULL when the queue is
97 * empty. (A queue holding NULL elements cannot tell empty from a NULL root via
98 * this call; use `pqmh_len` if that matters.)
99 */
100[[nodiscard]] [[gnu::nonnull(1)]]
101void *pqmh_peek(const pqmh_t *pq);
102
103/**
104 * The number of elements currently in the queue.
105 */
106[[nodiscard]] [[gnu::nonnull(1)]]
107size_t pqmh_len(const pqmh_t *pq);
108
109/**
110 * Release the backing array and reset the queue to empty. The elements
111 * themselves are not touched -- their lifetime belongs to the caller.
112 */
113[[gnu::nonnull(1, 2)]]
114void pqmh_free(srn_context_t *ctx, pqmh_t *pq);
void pqmh_free(srn_context_t *ctx, pqmh_t *pq)
Release the backing array and reset the queue to empty.
Definition pqmh.c:142
void pqmh_push(srn_context_t *ctx, pqmh_t *pq, void *elem)
Insert elem, growing the backing array (doubling) if it is full.
Definition pqmh.c:92
pqmh_t pqmh_make(srn_context_t *ctx, const pqmh_control_t *ctl, size_t initial_cap)
Create an empty queue ordered by ctl, with room for initial_cap elements (a small default is used whe...
Definition pqmh.c:81
void * pqmh_peek(const pqmh_t *pq)
The highest priority element without removing it, or NULL when the queue is empty.
Definition pqmh.c:132
bool pqmh_pop(srn_context_t *ctx, pqmh_t *pq, void **out)
Remove the highest priority element into *out and return true, or return false (leaving *out untouche...
Definition pqmh.c:111
size_t pqmh_len(const pqmh_t *pq)
The number of elements currently in the queue.
Definition pqmh.c:137
bool(* pqmh_less_fn)(srn_context_t *ctx, const void *a, const void *b)
Strict weak ordering predicate over two elements.
Definition pqmh.h:50
Per type configuration.
Definition pqmh.h:57
pqmh_less_fn less
Definition pqmh.h:58
A priority queue.
Definition pqmh.h:66
size_t cap
Definition pqmh.h:70
size_t len
Definition pqmh.h:69
void ** data
Definition pqmh.h:68
const pqmh_control_t * ctl
Definition pqmh.h:67