summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-11-06 22:14:58 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-11-06 22:14:58 -0500
commitc081c633f4980bcd39233526304b0cc44277ba07 (patch)
tree270060530eef5172635f8843a0f2c819271e8c64
parent5d1a7cce1fc0766c50054715d9f48525b362411a (diff)
pke: update pk.h to 0.9.6
-rw-r--r--src/pk.h128
1 files changed, 102 insertions, 26 deletions
diff --git a/src/pk.h b/src/pk.h
index c1ab0e9..1709de5 100644
--- a/src/pk.h
+++ b/src/pk.h
@@ -1,7 +1,7 @@
#ifndef PK_SINGLE_HEADER_FILE_H
#define PK_SINGLE_HEADER_FILE_H
/*******************************************************************************
-* PK Single-Header-Library V0.9.5
+* PK Single-Header-Library V0.9.6
*
* Author: Jonathan Bradley
* Copyright: © 2024-2025 Jonathan Bradley
@@ -303,7 +303,7 @@
*
*******************************************************************************/
-#define PK_VERSION "0.9.5"
+#define PK_VERSION "0.9.6"
#ifdef PK_IMPL_ALL
# ifndef PK_IMPL_MEM_TYPES
@@ -1501,6 +1501,10 @@ typedef uint64_t pk_ev_mgr_id_T;
typedef uint64_t pk_ev_id_T;
typedef uint64_t pk_ev_cb_id_T;
+const pk_ev_mgr_id_T pk_ev_mgr_id_T_MAX = 0xFFFFFFFFFFFFFFFF;
+const pk_ev_id_T pk_ev_id_T_MAX = 0xFFFFFFFFFFFFFFFF;
+const pk_ev_cb_id_T pk_ev_cb_id_T_MAX = 0xFFFFFFFFFFFFFFFF;
+
// TODO re-think threading
// note: pk_ev_init() is NOT thread-safe
@@ -1517,6 +1521,7 @@ pk_ev_id_T pk_ev_register_ev(pk_ev_mgr_id_T evmgr, void *user_ev_data);
pk_ev_cb_id_T pk_ev_register_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_fn *cb, void *user_cb_data);
void pk_ev_emit(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, void *user_emit_data);
+void pk_ev_unregister_ev(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid);
void pk_ev_unregister_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_id_T cbid);
#endif /* PK_EV_H */
@@ -1528,9 +1533,7 @@ void pk_ev_unregister_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_id_T cb
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <threads.h>
-#include <string.h>
#ifndef PK_EV_INIT_MGR_COUNT
# define PK_EV_INIT_MGR_COUNT 1
@@ -1548,6 +1551,12 @@ void pk_ev_unregister_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_id_T cb
# define PK_EV_GROW_RATIO 1.5
#endif
+// hard limits
+// PK_EV_MAX_EV_COUNT would require a refactor for keeping track of used slots
+#define PK_EV_MAX_EV_COUNT 64
+// PK_EV_MAX_CB_COUNT could be increased as desired
+#define PK_EV_MAX_CB_COUNT 255
+
#ifndef PK_EV_MEM_ALLOC
# define PK_EV_MEM_ALLOC(sz, alignment, bkt) pk_new(sz, alignment, bkt)
#endif
@@ -1570,7 +1579,9 @@ struct pk_ev {
struct pk_ev_mgr {
struct pk_ev *ev;
- atomic_uint_fast64_t n_ev;
+ atomic_uint_fast64_t left_evs;
+ atomic_uint_fast64_t right_evs;
+ atomic_uint_fast64_t unused_evs;
// reserved length of `pk_ev`s on this struct
atomic_uint_fast64_t rn_ev;
// on any given `pk_ev`, the number of callbacks reserved
@@ -1610,6 +1621,8 @@ pk_ev_inner_calc_sz(uint64_t ev_count, uint64_t cb_count, size_t *sz_ev_list, si
// base sizes
size_t l_sz_ev_list = sizeof(struct pk_ev) * ev_count;
size_t l_sz_ev_cb_list = sizeof(struct pk_ev_cb) * cb_count;
+ l_sz_ev_list += ((size_t)64 - alignof(struct pk_ev)) % (size_t)64;
+ l_sz_ev_cb_list += ((size_t)64 - alignof(struct pk_ev_cb)) % (size_t)64;
if (sz_ev_list != nullptr) *sz_ev_list = l_sz_ev_list;
if (sz_ev_cb_list != nullptr) *sz_ev_cb_list = l_sz_ev_cb_list;
@@ -1648,29 +1661,43 @@ pk_ev_inner_ev_mgr_create(uint64_t ev_count, uint64_t cb_count)
assert(ev_count < 0x100);
assert(cb_count < 0x100);
uint64_t i;
+ char *ptr;
struct pk_ev *ev;
size_t sz_ev_list;
size_t sz_ev_cb_list;
- size_t sz = pk_ev_inner_calc_sz(ev_count, cb_count, &sz_ev_list, &sz_ev_cb_list);
size_t sz_offset;
+ size_t sz = pk_ev_inner_calc_sz(ev_count, cb_count, &sz_ev_list, &sz_ev_cb_list);
struct pk_ev_mgr *mgr = (struct pk_ev_mgr*)PK_EV_MEM_ALLOC(sz, alignof(struct pk_ev_mgr), pk_ev_mstr.bkt);
if (mgr == NULL) goto early_exit;
- mgr->ev = (struct pk_ev*)(((char *)mgr) + sizeof(struct pk_ev_mgr));
+ ptr = ((char *)mgr) + sizeof(struct pk_ev_mgr);
+ sz_offset = (size_t)ptr % alignof(struct pk_ev);
+ ptr += ((size_t)64 - sz_offset) % (size_t)64;
+ mgr->ev = (struct pk_ev*)ptr;
atomic_init(&mgr->rn_ev, ev_count);
atomic_init(&mgr->rn_cb, cb_count);
- atomic_init(&mgr->n_ev, 0);
+ atomic_init(&mgr->left_evs, 0);
+ atomic_init(&mgr->right_evs, 0);
+ atomic_init(&mgr->unused_evs, 0xFFFFFFFFFFFFFFFF);
+ // find mem-aligned beginning of cb array
+ ptr += sz_ev_list;
+ sz_offset = (size_t)ptr % alignof(struct pk_ev_cb);
+ ptr += ((size_t)64 - sz_offset) % (size_t)64;
for (i = 0; i < ev_count; ++i) {
ev = &mgr->ev[i];
atomic_init(&ev->left_ev_cbs, 0);
atomic_init(&ev->right_ev_cbs, 0);
- sz_offset = sizeof(struct pk_ev_mgr);
- sz_offset += sz_ev_list;
- sz_offset += sz_ev_cb_list * i;
- ev->ev_cbs = (struct pk_ev_cb*)(((char *)mgr) + sz_offset);
+ sz_offset = sz_ev_cb_list * i;
+ ev->ev_cbs = (struct pk_ev_cb*)(ptr + sz_offset);
}
+ /* debug
+ fprintf(stdout, "[%s] mgr: sz: %lu, ev_count: %lu, cb_count: %lu \n", __FILE__, sz, ev_count, cb_count);
+ fprintf(stdout, "\t%p - ptr\n", (void*)mgr);
+ fprintf(stdout, "\t%p - evs (+%lu)\n", (void*)mgr->ev, (char*)mgr->ev - (char*)mgr);
+ fprintf(stdout, "\t%p - cbs (+%lu)\n", (void*)mgr->ev[0].ev_cbs, (char*)mgr->ev[0].ev_cbs - (char*)mgr);
+ */
early_exit:
return mgr;
}
@@ -1678,17 +1705,23 @@ early_exit:
static void
pk_ev_inner_ev_mgr_clone(struct pk_ev_mgr *old, struct pk_ev_mgr *mgr)
{
- uint64_t i;
+ uint64_t i, ii;
+ uint64_t u, uu;
struct pk_ev *ev_old;
struct pk_ev *ev;
- atomic_store(&mgr->n_ev, atomic_load(&old->n_ev));
- size_t old_sz_ev_cb_list;
- for (i = 0; i < old->n_ev; ++i) {
+ ii = atomic_load(&old->right_evs);
+ atomic_store(&mgr->left_evs, atomic_load(&old->left_evs));
+ atomic_store(&mgr->right_evs, ii);
+ atomic_store(&mgr->unused_evs, atomic_load(&old->unused_evs));
+ for (i = 0; i < ii; ++i) {
ev_old = &old->ev[i];
ev = &mgr->ev[i];
- pk_ev_inner_calc_sz(0, atomic_load(&ev_old->right_ev_cbs), nullptr, &old_sz_ev_cb_list);
ev->user_ev_data = ev_old->user_ev_data;
- memcpy(ev->ev_cbs, ev_old->ev_cbs, old_sz_ev_cb_list);
+ uu = atomic_load(&ev_old->right_ev_cbs);
+ for (u = 0; u <= uu; ++u) {
+ ev->ev_cbs[u].cb = ev_old->ev_cbs[u].cb;
+ ev->ev_cbs[u].user_cb_data = ev_old->ev_cbs[u].user_cb_data;
+ }
atomic_store(&ev->left_ev_cbs, atomic_load(&ev_old->left_ev_cbs));
atomic_store(&ev->right_ev_cbs, atomic_load(&ev_old->right_ev_cbs));
}
@@ -1755,12 +1788,15 @@ pk_ev_register_ev(pk_ev_mgr_id_T evmgr, void *user_ev_data)
{
assert(evmgr < 64);
uint64_t new_size;
+ uint64_t i, ii, flg;
pk_ev_id_T id;
+ bool found = false;
struct pk_ev_mgr *mgr = nullptr;
mtx_lock(&pk_ev_mstr.mtxs[evmgr]);
- if (pk_ev_mstr.mgrs[evmgr]->n_ev == pk_ev_mstr.mgrs[evmgr]->rn_ev) {
- new_size = PK_MAX(2, PK_MIN(255, pk_ev_mstr.mgrs[evmgr]->rn_ev * PK_EV_GROW_RATIO));
- if (new_size == pk_ev_mstr.mgrs[evmgr]->rn_ev) {
+ mgr = pk_ev_mstr.mgrs[evmgr];
+ if (mgr->left_evs == mgr->right_evs && mgr->right_evs == mgr->rn_ev) {
+ new_size = PK_MAX(2, PK_MIN(PK_EV_MAX_EV_COUNT, mgr->rn_ev * PK_EV_GROW_RATIO));
+ if (new_size == mgr->rn_ev) {
PK_LOG_ERR("[pkev.h] need more room, but failed to grow ev count.\n");
mtx_unlock(&pk_ev_mstr.mtxs[evmgr]);
exit(1);
@@ -1771,16 +1807,36 @@ pk_ev_register_ev(pk_ev_mgr_id_T evmgr, void *user_ev_data)
PK_EV_MEM_FREE(pk_ev_mstr.mgrs[evmgr], old_sz, pk_ev_mstr.bkt);
pk_ev_mstr.mgrs[evmgr] = mgr;
}
- id = pk_ev_mstr.mgrs[evmgr]->n_ev++;
+ id = atomic_load(&mgr->left_evs);
+ if (mgr->left_evs != mgr->right_evs) {
+ i = atomic_load(&mgr->left_evs);
+ ii = atomic_load(&mgr->rn_ev);
+ flg = atomic_load(&mgr->unused_evs);
+ for (; i < ii; ++i) {
+ if (flg & (1lu << i)) {
+ if (!found) {
+ found = true;
+ flg &= ~(1lu << i);
+ continue;
+ }
+ break;
+ }
+ }
+ atomic_store(&mgr->left_evs, i);
+ atomic_store(&mgr->unused_evs, flg);
+ } else {
+ atomic_store(&mgr->left_evs, atomic_load(&mgr->left_evs) + 1);
+ atomic_store(&mgr->right_evs, atomic_load(&mgr->right_evs) + 1);
+ }
mtx_unlock(&pk_ev_mstr.mtxs[evmgr]);
- pk_ev_mstr.mgrs[evmgr]->ev[id].user_ev_data = user_ev_data;
+ mgr->ev[id].user_ev_data = user_ev_data;
return id;
}
pk_ev_cb_id_T
pk_ev_register_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_fn *cb, void *user_cb_data)
{
- assert(evmgr < 64);
+ assert(evmgr < PK_EV_INIT_MGR_COUNT);
bool found = false;
uint64_t new_size, i;
struct pk_ev_mgr *mgr = nullptr;
@@ -1805,7 +1861,7 @@ pk_ev_register_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_fn *cb, void *
mtx_lock(&pk_ev_mstr.mtxs[evmgr]);
if (pk_ev_mstr.mgrs[evmgr]->ev[evid].right_ev_cbs == pk_ev_mstr.mgrs[evmgr]->rn_cb) {
size_t old_sz = pk_ev_inner_calc_sz(pk_ev_mstr.mgrs[evmgr]->rn_ev, pk_ev_mstr.mgrs[evmgr]->rn_cb, NULL, NULL);
- new_size = PK_MAX(2, PK_MIN(255, pk_ev_mstr.mgrs[evmgr]->rn_cb * PK_EV_GROW_RATIO));
+ new_size = PK_MAX(2, PK_MIN(PK_EV_MAX_CB_COUNT, pk_ev_mstr.mgrs[evmgr]->rn_cb * PK_EV_GROW_RATIO));
if (new_size == pk_ev_mstr.mgrs[evmgr]->rn_cb) {
PK_LOG_ERR("[pkev.h] need more room, but failed to grow cb count.\n");
mtx_unlock(&pk_ev_mstr.mtxs[evmgr]);
@@ -1831,7 +1887,7 @@ pk_ev_register_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_fn *cb, void *
void
pk_ev_emit(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, void *user_emit_data)
{
- assert(evmgr < 64);
+ assert(evmgr < PK_EV_INIT_MGR_COUNT);
uint8_t i;
for (i = 0; i < pk_ev_mstr.mgrs[evmgr]->ev[evid].right_ev_cbs; ++i) {
if (pk_ev_mstr.mgrs[evmgr] == nullptr) continue;
@@ -1844,6 +1900,26 @@ pk_ev_emit(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, void *user_emit_data)
}
void
+pk_ev_unregister_ev(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid)
+{
+ assert(evmgr <= pk_ev_mstr.rn_mgrs);
+ struct pk_ev_mgr *mgr = pk_ev_mstr.mgrs[evmgr];
+ assert(evid <= mgr->right_evs);
+ if (mgr == nullptr) return;
+ mgr->ev[evid].user_ev_data = NULL;
+ atomic_store(&mgr->ev[evid].left_ev_cbs, 0);
+ atomic_store(&mgr->ev[evid].right_ev_cbs, 0);
+ for (uint64_t u = 0; u < mgr->rn_cb; ++u) {
+ mgr->ev[evid].ev_cbs[u].cb = NULL;
+ mgr->ev[evid].ev_cbs[u].user_cb_data = NULL;
+ }
+ atomic_store(&mgr->unused_evs, atomic_load(&mgr->unused_evs) | (1lu << evid));
+ if (evid < atomic_load(&mgr->left_evs)) {
+ atomic_store(&mgr->left_evs, evid);
+ }
+}
+
+void
pk_ev_unregister_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_id_T cbid)
{
struct pk_ev_mgr *mgr = pk_ev_mstr.mgrs[evmgr];