Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
pqmh.h File Reference

A generic priority queue backed by a binary min-heap. More...

#include <stddef.h>
Include dependency graph for pqmh.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  pqmh_control_t
 Per type configuration. More...
struct  pqmh_t
 A priority queue. More...

Typedefs

typedef bool(* pqmh_less_fn) (srn_context_t *ctx, const void *a, const void *b)
 Strict weak ordering predicate over two elements.
typedef struct pqmh_control_t pqmh_control_t
 Per type configuration.
typedef struct pqmh_t pqmh_t
 A priority queue.

Functions

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 when 0).
void pqmh_push (srn_context_t *ctx, pqmh_t *pq, void *elem)
 Insert elem, growing the backing array (doubling) if it is full.
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 untouched) when the queue is empty.
void * pqmh_peek (const pqmh_t *pq)
 The highest priority element without removing it, or NULL when the queue is empty.
size_t pqmh_len (const pqmh_t *pq)
 The number of elements currently in the queue.
void pqmh_free (srn_context_t *ctx, pqmh_t *pq)
 Release the backing array and reset the queue to empty.

Detailed Description

A generic priority queue backed by a binary min-heap.

Elements are stored by pointer (void *), and the ordering is supplied through a control vtable (pqmh_control_t), so the same heap serves any element type – the only thing that varies per type is the comparison. The element the control orders first is the one at the root, returned by pqmh_peek and removed by pqmh_pop. A "less" predicate that returns a < b yields a min-heap, its inverse a max-heap.

This is a mutable, growable container. Its backing array is held in the manual lifetime allocator (srn_mm_malloc/srn_mm_reallocate/srn_mm_free) and grows by doubling, so a pqmh_t must be released with pqmh_free. By convention the operations take a srn_context_t * and reach the memory manager through ctx->engine->mm.

It is not synchronized; a pqmh_t is owned by a single thread and IS NOT THREAD SAFE.

Definition in file pqmh.h.

Typedef Documentation

◆ pqmh_control_t

typedef struct pqmh_control_t pqmh_control_t

Per type configuration.

Only the comparison varies between element types. The heap operations themselves are type independent, so the control carries just the ordering predicate.

◆ pqmh_less_fn

typedef bool(* pqmh_less_fn) (srn_context_t *ctx, const void *a, const void *b)

Strict weak ordering predicate over two elements.

Returns true when a should leave the queue before b (for a min-heap, when a < b). ctx is the context handed to the operation, for comparators that need it.

Definition at line 50 of file pqmh.h.

◆ pqmh_t

typedef struct pqmh_t pqmh_t

A priority queue.

data is the backing heap array of element pointers, len the live count, cap the allocated capacity. The control is bound at pqmh_make and not re-passed per operation.

Function Documentation

◆ pqmh_free()

void pqmh_free ( srn_context_t * ctx,
pqmh_t * pq )

Release the backing array and reset the queue to empty.

The elements themselves are not touched – their lifetime belongs to the caller.

Definition at line 142 of file pqmh.c.

142 {
143 PANIC_IF_NULL(ctx);
144 PANIC_IF_NULL(pq);
145
146 srn_mm_free(ctx->engine->mm, (void *)pq->data);
147 pq->data = nullptr;
148 pq->len = 0;
149 pq->cap = 0;
150}
void srn_mm_free(srn_mm_t *mm, void *ptr)
Release a pointer previously returned by srn_mm_malloc or srn_mm_reallocate.
Definition default.c:165
size_t cap
Definition pqmh.h:70
size_t len
Definition pqmh.h:69
void ** data
Definition pqmh.h:68
srn_engine_t * engine
Long term state of the compiler.
Definition context.h:49
srn_mm_t * mm
Memory manager.
Definition engine.h:65
#define PANIC_IF_NULL(ptr)
Definition utils.h:66
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pqmh_len()

size_t pqmh_len ( const pqmh_t * pq)
nodiscard

The number of elements currently in the queue.

Definition at line 137 of file pqmh.c.

137 {
138 PANIC_IF_NULL(pq);
139 return pq->len;
140}
Here is the caller graph for this function:

◆ pqmh_make()

pqmh_t pqmh_make ( srn_context_t * ctx,
const pqmh_control_t * ctl,
size_t initial_cap )
nodiscard

Create an empty queue ordered by ctl, with room for initial_cap elements (a small default is used when 0).

The backing array comes from the manual allocator, so the queue must later be released with pqmh_free.

Definition at line 81 of file pqmh.c.

81 {
82 PANIC_IF_NULL(ctx);
83 PANIC_IF_NULL(ctl);
84
85 size_t cap = (initial_cap == 0) ? PQMH_MIN_CAP : initial_cap;
86 void **data = (void **)srn_mm_malloc(ctx->engine->mm, cap * sizeof(void *));
87 PANIC_IF_NULL(data);
88
89 return (pqmh_t){.ctl = ctl, .data = data, .len = 0, .cap = cap};
90}
void * srn_mm_malloc(srn_mm_t *mm, size_t size)
Generic allocations that do not participate in the block based pools.
Definition default.c:155
#define PQMH_MIN_CAP
Capacity a queue created with initial_cap == 0 starts at.
Definition pqmh.c:27
A priority queue.
Definition pqmh.h:66
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pqmh_peek()

void * pqmh_peek ( const pqmh_t * pq)
nodiscard

The highest priority element without removing it, or NULL when the queue is empty.

(A queue holding NULL elements cannot tell empty from a NULL root via this call; use pqmh_len if that matters.)

Definition at line 132 of file pqmh.c.

132 {
133 PANIC_IF_NULL(pq);
134 return (pq->len == 0) ? nullptr : pq->data[0];
135}
Here is the caller graph for this function:

◆ pqmh_pop()

bool pqmh_pop ( srn_context_t * ctx,
pqmh_t * pq,
void ** out )
nodiscard

Remove the highest priority element into *out and return true, or return false (leaving *out untouched) when the queue is empty.

Definition at line 111 of file pqmh.c.

111 {
112 PANIC_IF_NULL(ctx);
113 PANIC_IF_NULL(pq);
114 PANIC_IF_NULL(out);
115
116 if (pq->len == 0) {
117 return false;
118 }
119
120 *out = pq->data[0];
121 pq->len--;
122
123 if (pq->len > 0) {
124 // Promote the last element to the root and sink it into place.
125 pq->data[0] = pq->data[pq->len];
126 sift_down(ctx, pq, 0);
127 }
128
129 return true;
130}
static void sift_down(srn_context_t *ctx, pqmh_t *pq, size_t i)
Move the element at i down toward the leaves until the heap order holds (neither child is ordered bef...
Definition pqmh.c:56
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pqmh_push()

void pqmh_push ( srn_context_t * ctx,
pqmh_t * pq,
void * elem )

Insert elem, growing the backing array (doubling) if it is full.

Panics if the growth allocation fails.

Definition at line 92 of file pqmh.c.

92 {
93 PANIC_IF_NULL(ctx);
94 PANIC_IF_NULL(pq);
95
96 if (pq->len == pq->cap) {
97 PANIC_IF(pq->cap > SIZE_MAX / 2 / sizeof(void *), "priority queue capacity overflows");
98 size_t new_cap = pq->cap * 2;
99 void **new_data =
100 (void **)srn_mm_reallocate(ctx->engine->mm, (void *)pq->data, new_cap * sizeof(void *));
101 PANIC_IF_NULL(new_data);
102 pq->data = new_data;
103 pq->cap = new_cap;
104 }
105
106 pq->data[pq->len] = elem;
107 pq->len++;
108 sift_up(ctx, pq, pq->len - 1);
109}
void * srn_mm_reallocate(srn_mm_t *mm, void *ptr, size_t new_size)
Definition default.c:160
static void sift_up(srn_context_t *ctx, pqmh_t *pq, size_t i)
Move the element at i up toward the root until the heap order holds (its parent is no longer ordered ...
Definition pqmh.c:36
#define PANIC_IF(cond, msg)
Definition utils.h:59
Here is the call graph for this function:
Here is the caller graph for this function: