diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-02-25 18:35:00 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-02-25 18:35:00 -0500 |
| commit | b6a1b507acbac6d601f8a0ba9f3727dd2f8f86e6 (patch) | |
| tree | f6a0fd847f31b9252ea6e891e63b229a26deb0a8 | |
| parent | a752cef28a4eda5f56c6a611198134d388eaa00b (diff) | |
pkev: unregister callbacks
| -rw-r--r-- | pkev.h | 97 | ||||
| -rw-r--r-- | test/pkev.c | 48 |
2 files changed, 110 insertions, 35 deletions
@@ -5,6 +5,7 @@ typedef uint64_t pk_ev_mgr_id_T; typedef uint64_t pk_ev_id_T; +typedef uint64_t pk_ev_cb_id_T; // note: pk_ev_init() is NOT thread-safe void pk_ev_init(); @@ -17,9 +18,11 @@ void pk_ev_destroy_mgr(pk_ev_mgr_id_T evmgr); typedef void (pk_ev_cb_fn)(void *user_event_data, void *user_cb_data, void *user_ev_data); pk_ev_id_T pk_ev_register_ev(pk_ev_mgr_id_T evmgr, void *user_ev_data); -bool pk_ev_register_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_fn *cb, void *user_cb_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_cb(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, pk_ev_cb_id_T cbid); + #endif /* PK_EV_H */ #ifdef PK_IMPL_EV @@ -58,14 +61,17 @@ struct pk_ev_cb { struct pk_ev { struct pk_ev_cb *ev_cbs; void *user_ev_data; - atomic_uint_fast8_t n_ev_cbs; + atomic_uint_fast64_t left_ev_cbs; + atomic_uint_fast64_t right_ev_cbs; }; struct pk_ev_mgr { struct pk_ev *ev; - atomic_uint_fast8_t n_ev; - atomic_uint_fast8_t rn_ev; - atomic_uint_fast8_t rn_cb; + atomic_uint_fast64_t n_ev; + // 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 + atomic_uint_fast64_t rn_cb; }; struct pk_ev_mstr { @@ -115,7 +121,7 @@ pk_ev_inner_ev_mgr_create(uint64_t ev_count, uint64_t cb_count) { assert(ev_count < 0x100); assert(cb_count < 0x100); - int i; + uint64_t i; struct pk_ev *ev; size_t sz = sizeof(struct pk_ev_mgr) + ((sizeof(struct pk_ev) * ev_count)) + (sizeof (struct pk_ev_cb) * ev_count * cb_count); size_t sz_ev = (sizeof(struct pk_ev_cb) * cb_count); @@ -130,7 +136,8 @@ pk_ev_inner_ev_mgr_create(uint64_t ev_count, uint64_t cb_count) atomic_init(&mgr->n_ev, 0); for (i = 0; i < mgr->rn_ev; ++i) { ev = &mgr->ev[i]; - atomic_init(&ev->n_ev_cbs, 0); + atomic_init(&ev->left_ev_cbs, 0); + atomic_init(&ev->right_ev_cbs, 0); ev->ev_cbs = (struct pk_ev_cb*)(((char *)mgr) + sizeof(struct pk_ev_mgr) + sz_evs + (sz_ev * i)); } @@ -141,15 +148,15 @@ early_exit: static void pk_ev_inner_ev_mgr_clone(struct pk_ev_mgr *old, struct pk_ev_mgr *mgr) { - int i; + uint64_t i; struct pk_ev *ev_old; struct pk_ev *ev; atomic_store(&mgr->n_ev, atomic_load(&old->n_ev)); for (i = 0; i < old->n_ev; ++i) { ev_old = &old->ev[i]; ev = &mgr->ev[i]; - memcpy(ev->ev_cbs, ev_old->ev_cbs, sizeof(struct pk_ev_cb) * atomic_load(&ev_old->n_ev_cbs)); - atomic_store(&ev->n_ev_cbs, atomic_load(&ev_old->n_ev_cbs)); + memcpy(ev->ev_cbs, ev_old->ev_cbs, sizeof(struct pk_ev_cb) * atomic_load(&ev_old->right_ev_cbs)); + atomic_store(&ev->right_ev_cbs, atomic_load(&ev_old->right_ev_cbs)); } } @@ -221,31 +228,55 @@ pk_ev_register_ev(pk_ev_mgr_id_T evmgr, void *user_ev_data) return id; } -bool +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); - uint64_t new_size; + bool found = false; + uint64_t new_size, i; struct pk_ev_mgr *mgr; - uint8_t cb_index; + pk_ev_cb_id_T cb_index; + + mgr = pk_ev_mstr.mgrs[evmgr]; + if (mgr == nullptr) { + PK_LOGV_ERR("[pkev.h] unknown event: '%lu'.\n", evmgr); + exit(1); + } mtx_lock(&pk_ev_mstr.mtxs[evmgr]); - if (pk_ev_mstr.mgrs[evmgr]->ev[evid].n_ev_cbs == pk_ev_mstr.mgrs[evmgr]->rn_cb) { - new_size = PK_MAX(2, PK_MIN(255, 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]); - exit(1); + for (i = mgr->ev[evid].left_ev_cbs; i < mgr->ev[evid].right_ev_cbs; ++i) { + if (found == false && mgr->ev[evid].ev_cbs[i].cb != nullptr) { + found = true; + cb_index = i; + continue; + } + if (found == false) continue; + if (mgr->ev[evid].ev_cbs[i].cb == nullptr) { + mgr->ev[evid].left_ev_cbs = i; + break; + } + } + if (found == false) { + if (pk_ev_mstr.mgrs[evmgr]->ev[evid].right_ev_cbs == pk_ev_mstr.mgrs[evmgr]->rn_cb) { + new_size = PK_MAX(2, PK_MIN(255, 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]); + exit(1); + } + mgr = pk_ev_inner_ev_mgr_create(pk_ev_mstr.mgrs[evmgr]->rn_ev, new_size); + pk_ev_inner_ev_mgr_clone(pk_ev_mstr.mgrs[evmgr], mgr); + free(pk_ev_mstr.mgrs[evmgr]); + pk_ev_mstr.mgrs[evmgr] = mgr; + } + cb_index = pk_ev_mstr.mgrs[evmgr]->ev[evid].right_ev_cbs++; + if (cb_index == pk_ev_mstr.mgrs[evmgr]->ev[evid].left_ev_cbs) { + pk_ev_mstr.mgrs[evmgr]->ev[evid].left_ev_cbs++; } - mgr = pk_ev_inner_ev_mgr_create(pk_ev_mstr.mgrs[evmgr]->rn_ev, new_size); - pk_ev_inner_ev_mgr_clone(pk_ev_mstr.mgrs[evmgr], mgr); - free(pk_ev_mstr.mgrs[evmgr]); - pk_ev_mstr.mgrs[evmgr] = mgr; } - cb_index = pk_ev_mstr.mgrs[evmgr]->ev[evid].n_ev_cbs++; pk_ev_mstr.mgrs[evmgr]->ev[evid].ev_cbs[cb_index].cb = cb; pk_ev_mstr.mgrs[evmgr]->ev[evid].ev_cbs[cb_index].user_cb_data = user_cb_data; mtx_unlock(&pk_ev_mstr.mtxs[evmgr]); - return true; + return cb_index; } void @@ -253,7 +284,9 @@ pk_ev_emit(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, void *user_emit_data) { assert(evmgr < 64); uint8_t i; - for (i = 0; i < pk_ev_mstr.mgrs[evmgr]->ev[evid].n_ev_cbs; ++i) { + for (i = 0; i < pk_ev_mstr.mgrs[evmgr]->ev[evid].right_ev_cbs; ++i) { + if (pk_ev_mstr.mgrs[evmgr] == nullptr) continue; + if (pk_ev_mstr.mgrs[evmgr]->ev[evid].ev_cbs[i].cb == nullptr) continue; (*pk_ev_mstr.mgrs[evmgr]->ev[evid].ev_cbs[i].cb)( pk_ev_mstr.mgrs[evmgr]->ev[evid].user_ev_data, pk_ev_mstr.mgrs[evmgr]->ev[evid].ev_cbs[i].user_cb_data, @@ -261,4 +294,16 @@ pk_ev_emit(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, void *user_emit_data) } } +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]; + if (mgr == nullptr) return; + if (mgr->ev[evid].left_ev_cbs > cbid) { + mgr->ev[evid].left_ev_cbs = cbid; + } + mgr->ev[evid].ev_cbs[cbid].cb = nullptr; + mgr->ev[evid].ev_cbs[cbid].user_cb_data = nullptr; +} + #endif /* PK_IMPL_EV */ diff --git a/test/pkev.c b/test/pkev.c index 10d82b0..f28739b 100644 --- a/test/pkev.c +++ b/test/pkev.c @@ -8,7 +8,8 @@ struct ev { pk_ev_mgr_id_T evmgr; pk_ev_id_T evid; - bool handled; + pk_ev_cb_id_T evcbid; + int handled_count; }; struct ev ev_one = {0}; @@ -17,13 +18,13 @@ struct ev ev_two = {0}; void handle_ev_one(void *, void *, void *) { - ev_one.handled = true; + ev_one.handled_count++; } void handle_ev_two(void *, void *, void *) { - ev_two.handled = true; + ev_two.handled_count++; } int @@ -68,13 +69,42 @@ int main(int argc, char *argv[]) const pk_ev_mgr_id_T evmgr = test_setup(); ev_one.evid = pk_ev_register_ev(evmgr, NULL); ev_two.evid = pk_ev_register_ev(evmgr, NULL); - pk_ev_register_cb(evmgr, ev_one.evid, handle_ev_one, NULL); - pk_ev_register_cb(evmgr, ev_two.evid, handle_ev_two, NULL); + ev_one.evcbid = pk_ev_register_cb(evmgr, ev_one.evid, handle_ev_one, NULL); + ev_two.evcbid = pk_ev_register_cb(evmgr, ev_two.evid, handle_ev_two, NULL); + pk_ev_emit(evmgr, ev_one.evid, NULL); + pk_ev_emit(evmgr, ev_two.evid, NULL); + PK_LOGV_INF("%s: ev_one: %i, ev_two: %i\n", __FILE__, ev_one.handled_count, ev_two.handled_count); + pk_ev_teardown(); + if (ev_one.handled_count != 1 || ev_two.handled_count != 1) exit(1); + } + + // register, emit, catch + { + const pk_ev_mgr_id_T evmgr = test_setup(); + ev_one.evid = pk_ev_register_ev(evmgr, NULL); + ev_two.evid = pk_ev_register_ev(evmgr, NULL); + ev_one.evcbid = pk_ev_register_cb(evmgr, ev_one.evid, handle_ev_one, NULL); + ev_two.evcbid = pk_ev_register_cb(evmgr, ev_two.evid, handle_ev_two, NULL); + pk_ev_emit(evmgr, ev_one.evid, NULL); + pk_ev_emit(evmgr, ev_two.evid, NULL); + PK_LOGV_INF("%s: ev_one: %i, ev_two: %i\n", __FILE__, ev_one.handled_count, ev_two.handled_count); + pk_ev_unregister_cb(evmgr, ev_one.evid, ev_one.evcbid); + pk_ev_unregister_cb(evmgr, ev_two.evid, ev_two.evcbid); pk_ev_emit(evmgr, ev_one.evid, NULL); pk_ev_emit(evmgr, ev_two.evid, NULL); - PK_LOGV_INF("%s: ev_one: %b, ev_two: %b\n", __FILE__, ev_one.handled, ev_two.handled); + uint64_t left, right; + left = pk_ev_mstr.mgrs[ev_one.evmgr]->ev[ev_one.evid].left_ev_cbs; + right = pk_ev_mstr.mgrs[ev_one.evmgr]->ev[ev_one.evid].right_ev_cbs; + PK_LOGV_INF("%s: left: %lu, right: %lu\n", __FILE__, left, right); + left = pk_ev_mstr.mgrs[ev_two.evmgr]->ev[ev_two.evid].left_ev_cbs; + right = pk_ev_mstr.mgrs[ev_two.evmgr]->ev[ev_two.evid].right_ev_cbs; + PK_LOGV_INF("%s: left: %lu, right: %lu\n", __FILE__, left, right); + if (pk_ev_mstr.mgrs[ev_one.evmgr]->ev[ev_one.evid].left_ev_cbs != 0) exit (1); + if (pk_ev_mstr.mgrs[ev_one.evmgr]->ev[ev_one.evid].right_ev_cbs != 1) exit (1); + if (pk_ev_mstr.mgrs[ev_two.evmgr]->ev[ev_two.evid].left_ev_cbs != 0) exit (1); + if (pk_ev_mstr.mgrs[ev_two.evmgr]->ev[ev_two.evid].right_ev_cbs != 1) exit (1); pk_ev_teardown(); - if (ev_one.handled == false || ev_two.handled == false) exit(1); + if (ev_one.handled_count != 1 || ev_two.handled_count != 1) exit(1); } // threaded register, emit, catch @@ -89,9 +119,9 @@ int main(int argc, char *argv[]) thrd_create(&t2, thrd_ev_emit_two, NULL); thrd_join(t1, &i); thrd_join(t2, &i); - PK_LOGV_INF("%s: ev_one: %b, ev_two: %b\n", __FILE__, ev_one.handled, ev_two.handled); + PK_LOGV_INF("%s: ev_one: %i, ev_two: %i\n", __FILE__, ev_one.handled_count, ev_two.handled_count); pk_ev_teardown(); - if (ev_one.handled == false || ev_two.handled == false) exit(1); + if (ev_one.handled_count != 1 || ev_two.handled_count != 1) exit(1); } return 0; |
