summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-05-28 17:13:15 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-05-28 17:13:15 -0400
commit3a81898eed7eed7b220d280a8acc9c9cdceac7c0 (patch)
tree12f3c9cdc9725ee21098072fc689f6ed913e558c /src
parenta8b14fba55007002d3f1a24b3bfc2d1a63c7d578 (diff)
pk.h: update to 0.5.2
Diffstat (limited to 'src')
-rw-r--r--src/pk.h164
1 files changed, 160 insertions, 4 deletions
diff --git a/src/pk.h b/src/pk.h
index 10a9f5c..49e08f2 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.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 */