summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-02-25 18:35:00 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-02-25 18:35:00 -0500
commitb6a1b507acbac6d601f8a0ba9f3727dd2f8f86e6 (patch)
treef6a0fd847f31b9252ea6e891e63b229a26deb0a8
parenta752cef28a4eda5f56c6a611198134d388eaa00b (diff)
pkev: unregister callbacks
-rw-r--r--pkev.h97
-rw-r--r--test/pkev.c48
2 files changed, 110 insertions, 35 deletions
diff --git a/pkev.h b/pkev.h
index fcf0d2d..445180d 100644
--- a/pkev.h
+++ b/pkev.h
@@ -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;