diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-11-06 22:14:58 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-11-06 22:14:58 -0500 |
| commit | c081c633f4980bcd39233526304b0cc44277ba07 (patch) | |
| tree | 270060530eef5172635f8843a0f2c819271e8c64 | |
| parent | 5d1a7cce1fc0766c50054715d9f48525b362411a (diff) | |
pke: update pk.h to 0.9.6
| -rw-r--r-- | src/pk.h | 128 |
1 files changed, 102 insertions, 26 deletions
@@ -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]; |
