nova-nix-0.1.9.0: cbits/nn_list.c
/*
* nn_list.c — Contiguous array of thunk pointers for lists.
*
* Each nn_list_t is a small header (malloc'd, tracked) pointing to
* a contiguous items array (page-allocated via nn_env_alloc_slots).
* Bulk cleanup frees all headers; the page allocator frees items.
*/
#include "nn_list.h"
#include "nn_env.h"
#include "nn_assert.h"
#include <stdio.h>
#include <stdlib.h>
/* --- Global tracking for bulk cleanup --- */
static nn_list_t **g_tracked = NULL;
static uint32_t g_tracked_count = 0;
static uint32_t g_tracked_cap = 0;
static void nn_list_track(nn_list_t *list)
{
if (g_tracked_count >= g_tracked_cap) {
uint32_t new_cap = g_tracked_cap ? g_tracked_cap * 2 : 256;
nn_list_t **new_arr = (nn_list_t **)realloc(
g_tracked, (size_t)new_cap * sizeof(nn_list_t *));
if (!new_arr) {
fprintf(stderr, "nn_list_track: realloc failed\n");
abort();
}
g_tracked = new_arr;
g_tracked_cap = new_cap;
}
g_tracked[g_tracked_count++] = list;
}
/* --- Lifecycle --- */
nn_list_t *
nn_list_new(uint32_t count)
{
if (count == 0) return NULL;
nn_list_t *list = (nn_list_t *)malloc(sizeof(nn_list_t));
if (!list) return NULL;
/* Items array via the env page allocator (O(1) bump allocation).
* nn_env_alloc_slots returns void**, which we cast to nn_thunk**.
* All slots are zero-initialized (NULL pointers). */
list->items = (struct nn_thunk **)nn_env_alloc_slots(count);
list->count = count;
if (!list->items) {
free(list);
return NULL;
}
nn_list_track(list);
return list;
}
void
nn_list_free_all(void)
{
uint32_t i;
for (i = 0; i < g_tracked_count; i++) {
free(g_tracked[i]);
}
free(g_tracked);
g_tracked = NULL;
g_tracked_count = 0;
g_tracked_cap = 0;
}
/* --- Access --- */
uint32_t
nn_list_count(const nn_list_t *list)
{
return list->count;
}
struct nn_thunk *
nn_list_get(const nn_list_t *list, uint32_t index)
{
NN_ASSERT(index < list->count, "nn_list_get: index out of bounds");
return list->items[index];
}
void
nn_list_set(nn_list_t *list, uint32_t index, struct nn_thunk *thunk)
{
NN_ASSERT(index < list->count, "nn_list_set: index out of bounds");
list->items[index] = thunk;
}