diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-05-28 17:13:15 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-05-28 17:13:15 -0400 |
| commit | 3a81898eed7eed7b220d280a8acc9c9cdceac7c0 (patch) | |
| tree | 12f3c9cdc9725ee21098072fc689f6ed913e558c /src | |
| parent | a8b14fba55007002d3f1a24b3bfc2d1a63c7d578 (diff) | |
pk.h: update to 0.5.2
Diffstat (limited to 'src')
| -rw-r--r-- | src/pk.h | 164 |
1 files changed, 160 insertions, 4 deletions
@@ -1,7 +1,7 @@ #ifndef PK_SINGLE_HEADER_FILE_H #define PK_SINGLE_HEADER_FILE_H /******************************************************************************* -* PK Single-Header-Library V0.5.1 +* PK Single-Header-Library V0.5.2 * * Author: Jonathan Bradley * Copyright: © 2024-2025 Jonathan Bradley @@ -252,9 +252,30 @@ * arr.~pk_bkt_arr<int>(); // manually call dtor for globals * ``` * +******************************************************************************** +* pktmpl.h: only contains c++ templates, no IMPL. +* +* Provides template structs for trampolines, allowing c-style callbacks with +* capturing lambdas. +* +* Examples: +* ```c++ +* int some_counter = 0; +* using IterCbWrapper = pk_tmpln_1<void, int*, void*>; +* IterCbWrapper cb_wrapper{}; +* cb_wrapper.func = [&some_counter](int *lhs) +* { +* (void)lhs; +* some_counter += 1; +* return; +* }; +* pk_bkt_arr_iterate(&bkt_arr, &IterCbWrapper::invoke, &cb_wrapper); +* assert(some_count == 1); +* ``` +* *******************************************************************************/ -#define PK_VERSION "0.5.1" +#define PK_VERSION "0.5.2" #ifdef PK_IMPL_ALL # ifndef PK_IMPL_MEM_TYPES @@ -2532,14 +2553,32 @@ bool operator!=(const pk_uuid &lhs, const pk_uuid &rhs) { return !pk_uuid_equals #define PK_PKBKTARR_H +#ifndef PK_BKT_ARR_ALL_UNUSED_VAL + #define PK_BKT_ARR_ALL_UNUSED_VAL 0xFFFFFFFFFFFFFFFF +#endif #define PK_BKT_ARR_HANDLE_B_MAX 0xFFFFFF #define PK_BKT_ARR_HANDLE_I_MAX 64 +typedef bool (pk_bkt_arr_compare_fn)(void *user_data, const void *user_obj_data, const void *arr_obj_data); +typedef void (pk_bkt_arr_iterate_fn)(void *user_data, void *arr_obj_data); + struct pk_bkt_arr_handle { unsigned int b : 24; unsigned int i : 8; }; +#if ! defined(__cplusplus) +#define pk_bkt_arr_handle_MAX ((struct pk_bkt_arr_handle){ .b = PK_BKT_ARR_HANDLE_B_MAX, .i = PK_BKT_ARR_HANDLE_I_MAX }) +#else +#define pk_bkt_arr_handle_MAX (pk_bkt_arr_handle{ .b = PK_BKT_ARR_HANDLE_B_MAX, .i = PK_BKT_ARR_HANDLE_I_MAX }) +constexpr struct pk_bkt_arr_handle pk_bkt_arr_handle_MAX_constexpr = pk_bkt_arr_handle_MAX; +inline constexpr bool +operator==(const pk_bkt_arr_handle &lhs, const pk_bkt_arr_handle &rhs) +{ + return lhs.b == rhs.b && lhs.i == rhs.i; +} +#endif + struct pk_bkt_arr { struct pk_membucket *bkt_buckets; struct pk_membucket *bkt_data; @@ -2553,7 +2592,18 @@ struct pk_bkt_arr { unsigned long alignment; }; +enum PK_BKT_ARR_HANDLE_VALIDATION : uint8_t { + PK_BKT_ARR_HANDLE_VALIDATION_VALID = 0, + PK_BKT_ARR_HANDLE_VALIDATION_BUCKET_INDEX_TOO_HIGH = 1 << 0, + PK_BKT_ARR_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH = 2 << 1, +}; + +enum PK_BKT_ARR_HANDLE_VALIDATION pk_bkt_arr_handle_validate(struct pk_bkt_arr *bkt_arr, struct pk_bkt_arr_handle handle); + void pk_bkt_arr_init(struct pk_bkt_arr *bkt_arr, unsigned long stride, unsigned long alignment, struct pk_bkt_arr_handle limits, struct pk_membucket *bkt_buckets, struct pk_membucket *bkt_data); +void pk_bkt_arr_clear(struct pk_bkt_arr *bkt_arr); +struct pk_bkt_arr_handle pk_bkt_arr_find_first_handle(struct pk_bkt_arr *bkt_arr, pk_bkt_arr_compare_fn fn, void *user_data, const void *user_obj_data); +void pk_bkt_arr_iterate(struct pk_bkt_arr *bkt_arr, pk_bkt_arr_iterate_fn fn, void *user_data); void pk_bkt_arr_teardown(struct pk_bkt_arr *bkt_arr); struct pk_bkt_arr_handle pk_bkt_arr_new_handle(struct pk_bkt_arr *bkt_arr); void pk_bkt_arr_free_handle(struct pk_bkt_arr *bkt_arr, struct pk_bkt_arr_handle handle); @@ -2563,6 +2613,7 @@ struct pk_bkt_arr_handle pk_bkt_arr_handle_decrement(struct pk_bkt_arr *arr, str #if defined (__cplusplus) #include <assert.h> +#include <future> template<typename T> struct pk_bkt_arr_t : public pk_bkt_arr { pk_bkt_arr_t(); @@ -2600,6 +2651,20 @@ T &pk_bkt_arr_t<T>::operator[](struct pk_bkt_arr_handle handle) { #include <assert.h> #include <string.h> +enum PK_BKT_ARR_HANDLE_VALIDATION pk_bkt_arr_handle_validate(struct pk_bkt_arr *bkt_arr, struct pk_bkt_arr_handle handle) { + assert(bkt_arr != NULL); + uint8_t ret = 0; + if (handle.b >= bkt_arr->reserved_buckets || handle.b >= bkt_arr->limits.b) { + ret |= PK_BKT_ARR_HANDLE_VALIDATION_BUCKET_INDEX_TOO_HIGH; + } + if (handle.b == bkt_arr->reserved_buckets-1 && handle.i > bkt_arr->head_r.i) { + ret |= PK_BKT_ARR_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH; + } else if (handle.b < bkt_arr->reserved_buckets-1 && handle.i > bkt_arr->limits.i) { + ret |= PK_BKT_ARR_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH; + } + return (enum PK_BKT_ARR_HANDLE_VALIDATION)ret; +} + void pk_bkt_arr_init(struct pk_bkt_arr *bkt_arr, unsigned long stride, unsigned long alignment, struct pk_bkt_arr_handle limits, struct pk_membucket *bkt_buckets, struct pk_membucket *bkt_data) { assert(limits.b <= PK_BKT_ARR_HANDLE_B_MAX); @@ -2617,11 +2682,62 @@ void pk_bkt_arr_init(struct pk_bkt_arr *bkt_arr, unsigned long stride, unsigned bkt_arr->stride = stride; bkt_arr->alignment = alignment; bkt_arr->idx_unused = (unsigned long long *)pk_new(sizeof(unsigned long long), alignof(unsigned long long), bkt_buckets); - bkt_arr->idx_unused[0] = 0xFFFFFFFFFFFFFFFF; + bkt_arr->idx_unused[0] = PK_BKT_ARR_ALL_UNUSED_VAL; bkt_arr->bucketed_data = (void **)pk_new(sizeof(void *), alignof(void *), bkt_buckets); bkt_arr->bucketed_data[0] = pk_new(stride * limits.i, alignment, bkt_data); } +void pk_bkt_arr_clear(struct pk_bkt_arr *bkt_arr) { + unsigned int b; + bkt_arr->head_l.b = 0; + bkt_arr->head_l.i = 0; + bkt_arr->head_r.b = 0; + bkt_arr->head_r.i = 0; + for (b = 0; b < bkt_arr->reserved_buckets; ++b) { + bkt_arr->idx_unused[b] = PK_BKT_ARR_ALL_UNUSED_VAL; + } +} + +struct pk_bkt_arr_handle pk_bkt_arr_find_first_handle(struct pk_bkt_arr *bkt_arr, pk_bkt_arr_compare_fn fn, void *user_data, const void *user_obj_data) { + assert(bkt_arr != NULL); + assert(fn != NULL); + struct pk_bkt_arr_handle ret; + unsigned int b, i, ii; + ret.b = PK_BKT_ARR_HANDLE_B_MAX; + ret.i = PK_BKT_ARR_HANDLE_I_MAX; + for (b = 0; b < bkt_arr->reserved_buckets; ++b) { + char *arr = ((char**)(bkt_arr->bucketed_data))[b]; + ii = b == bkt_arr->reserved_buckets-1 ? bkt_arr->head_r.i : bkt_arr->limits.i; + for (i = 0; i < ii; ++i) { + if (PK_HAS_FLAG(bkt_arr->idx_unused[b], 1ull << i)) { + continue; + } + if (fn(user_data, user_obj_data, arr+(bkt_arr->stride * i))) { + ret.b = b; + ret.i = i; + return ret; + } + } + } + return ret; +} + +void pk_bkt_arr_iterate(struct pk_bkt_arr *bkt_arr, pk_bkt_arr_iterate_fn fn, void *user_data) { + assert(bkt_arr != NULL); + assert(fn != NULL); + unsigned int b, i, ii; + for (b = 0; b < bkt_arr->reserved_buckets; ++b) { + char *arr = ((char**)(bkt_arr->bucketed_data))[b]; + ii = b == bkt_arr->reserved_buckets-1 ? bkt_arr->head_r.i : bkt_arr->limits.i; + for (i = 0; i < ii; ++i) { + if (PK_HAS_FLAG(bkt_arr->idx_unused[b], 1ull << i)) { + continue; + } + fn(user_data, arr+(bkt_arr->stride * i)); + } + } +} + void pk_bkt_arr_teardown(struct pk_bkt_arr *bkt_arr) { int b; @@ -2633,6 +2749,10 @@ void pk_bkt_arr_teardown(struct pk_bkt_arr *bkt_arr) pk_delete((void *)bkt_arr->idx_unused, sizeof(unsigned long long) * (bkt_arr->reserved_buckets), bkt_arr->bkt_buckets); pk_delete((void *)bkt_arr->bucketed_data, sizeof(void *) * (bkt_arr->reserved_buckets), bkt_arr->bkt_buckets); memset(bkt_arr, 0, sizeof(struct pk_bkt_arr)); + bkt_arr->bkt_buckets = NULL; + bkt_arr->bkt_data = NULL; + bkt_arr->idx_unused = NULL; + bkt_arr->bucketed_data = NULL; } struct pk_bkt_arr_handle pk_bkt_arr_new_handle(struct pk_bkt_arr *bkt_arr) @@ -2673,7 +2793,7 @@ struct pk_bkt_arr_handle pk_bkt_arr_new_handle(struct pk_bkt_arr *bkt_arr) new_idx_unused[b] = bkt_arr->idx_unused[b]; new_data_ptrs[b] = bkt_arr->bucketed_data[b]; } - new_idx_unused[bkt_arr->reserved_buckets - 1] = 0xFFFFFFFFFFFFFFFF; + new_idx_unused[bkt_arr->reserved_buckets - 1] = PK_BKT_ARR_ALL_UNUSED_VAL; new_data_ptrs[bkt_arr->reserved_buckets - 1] = pk_new(bkt_arr->stride * bkt_arr->limits.i, bkt_arr->alignment, bkt_arr->bkt_data); pk_delete((void *)bkt_arr->idx_unused, sizeof(unsigned long long) * (bkt_arr->reserved_buckets - 1), bkt_arr->bkt_buckets); @@ -2692,6 +2812,7 @@ done: void pk_bkt_arr_free_handle(struct pk_bkt_arr *bkt_arr, struct pk_bkt_arr_handle handle) { assert(bkt_arr != nullptr); + assert(pk_bkt_arr_handle_validate(bkt_arr, handle) == PK_BKT_ARR_HANDLE_VALIDATION_VALID); bkt_arr->idx_unused[handle.b] |= (1ull << handle.i); if (handle.b < bkt_arr->head_l.b || (handle.b == bkt_arr->head_l.b && handle.i < bkt_arr->head_l.i)) { bkt_arr->head_l = handle; @@ -2735,4 +2856,39 @@ struct pk_bkt_arr_handle pk_bkt_arr_handle_decrement(struct pk_bkt_arr *arr, str } #endif /* PK_IMPL_BKTARR */ +#ifndef PK_PKTMPLN_H +#define PK_PKTMPLN_H + +#if defined (__cplusplus) +#include <functional> +template<typename Ret, typename A1, typename B1> +struct pk_tmpln_1 { + using FuncType = std::function<Ret(A1)>; + FuncType func; + static Ret invoke(void *ptr, B1 b1) { + auto *self = static_cast<pk_tmpln_1*>(ptr); + return self->func(reinterpret_cast<A1>(b1)); + } +}; +template<typename Ret, typename A1, typename A2, typename B1, typename B2> +struct pk_tmpln_2 { + using FuncType = std::function<Ret(A1, A2)>; + FuncType func; + static Ret invoke(void *ptr, B1 b1, B2 b2) { + auto *self = static_cast<pk_tmpln_2*>(ptr); + return self->func(reinterpret_cast<A1>(b1), reinterpret_cast<A2>(b2)); + } +}; +template<typename Ret, typename A1, typename A2, typename A3, typename B1, typename B2, typename B3> +struct pk_tmpln_3 { + using FuncType = std::function<Ret(A1, A2, A3)>; + FuncType func; + static Ret invoke(void *ptr, B1 b1, B2 b2, B3 b3) { + auto *self = static_cast<pk_tmpln_3*>(ptr); + return self->func(reinterpret_cast<A1>(b1), reinterpret_cast<A2>(b2), reinterpret_cast<A3>(b3)); + } +}; +#endif + +#endif /* PK_PKTMPLN_H */ #endif /* PK_SINGLE_HEADER_FILE_H */ |
