summaryrefslogtreecommitdiff
path: root/src/pk.h
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-01-14 13:57:35 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-01-14 13:57:35 -0500
commit46d814de510d0a7753c3e49eed3b3440d1c7c681 (patch)
tree91fef3ca83d1cced76bded305e0ead4f58a0d64d /src/pk.h
parent28f25f4c82ef7e712bc0c22f9ccb054efa584275 (diff)
pk.h: update to 0.2.0
Diffstat (limited to 'src/pk.h')
-rw-r--r--src/pk.h196
1 files changed, 122 insertions, 74 deletions
diff --git a/src/pk.h b/src/pk.h
index 49b735f..917a125 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.1.1
+* PK Single-Header-Library V0.2.0
*
* Author: Jonathan Bradley
* Copyright: © 2024-2025 Jonathan Bradley
@@ -178,7 +178,7 @@
*
*******************************************************************************/
-#define PK_VERSION "0.1.1"
+#define PK_VERSION "0.2.0"
#ifdef PK_IMPL_ALL
# ifndef PK_IMPL_MEM_TYPES
@@ -210,8 +210,8 @@
# define PK_LOGV_ERR(str, ...) (void)str
# define PK_LOGV_INF(str, ...) (void)str
# else
-# define PK_LOG_ERR(str, ...) fprintf(stderr, str)
-# define PK_LOG_INF(str, ...) fprintf(stdout, str)
+# define PK_LOG_ERR(str) fprintf(stderr, str)
+# define PK_LOG_INF(str) fprintf(stdout, str)
# define PK_LOGV_ERR(str, ...) fprintf(stderr, str, __VA_ARGS__)
# define PK_LOGV_INF(str, ...) fprintf(stdout, str, __VA_ARGS__)
# endif
@@ -435,13 +435,17 @@ struct pk_handle {
pk_handle_item_index_T itemIndex;
};
-#define PK_HANDLE_MAX ((struct pk_handle){ .bucketIndex = 0xFFFFFFFF, .itemIndex = 0xFFFFFFFF })
+#if ! defined(__cplusplus)
+ #define PK_HANDLE_MAX ((struct pk_handle){ .bucketIndex = 0xFFFFFFFF, .itemIndex = 0xFFFFFFFF })
+#else
+ #define PK_HANDLE_MAX (pk_handle{ 0xFFFFFFFF, 0xFFFFFFFF })
+#endif
enum PK_HANDLE_VALIDATION pk_handle_validate(const struct pk_handle handle, const struct pk_handle bucketHandle, const uint64_t maxItems);
#if defined(__cplusplus)
-constexpr struct pk_handle pk_handle_MAX_constexpr = (struct pk_handle){ .bucketIndex = 0xFFFFFFFF, .itemIndex = 0xFFFFFFFF };
+constexpr struct pk_handle pk_handle_MAX_constexpr = { 0xFFFFFFFF, 0xFFFFFFFF };
inline constexpr bool
operator==(const pk_handle& lhs, const pk_handle& rhs)
@@ -619,19 +623,19 @@ struct pk_memblock {
struct pk_membucket {
// the total size of the bucket, `blocks+ptr`
- int64_t size;
+ size_t size;
// the current head of the bucket: byte offset from `ptr`.
// All currently alloc'd data is before this offset
- int64_t head;
+ size_t head;
// amount of lost bytes in this membucket, hopefully zero
- int64_t lostBytes;
+ size_t lostBytes;
// the number of active allocations from this bucket
- int64_t allocs;
+ size_t allocs;
// the index of the last empty block.
// Should always point to `pk_memblock{ .data = ptr+head, .size=size-head }`
- int64_t lastEmptyBlockIndex;
+ size_t lastEmptyBlockIndex;
// number of pk_memblocks in the `*blocks` array
- int64_t maxBlockCount;
+ size_t maxBlockCount;
// ptr to an array of pk_memblock to track ALL free space between ptr and ptr+sz
struct pk_memblock* blocks;
// starting point for alloc'd data
@@ -645,7 +649,7 @@ struct pk_membucket {
};
static struct pk_membucket pk_buckets[PK_MAX_BUCKET_COUNT];
-static int64_t pk_bucket_head = 0;
+static size_t pk_bucket_head = 0;
#ifdef PK_MEMORY_DEBUGGER
struct pk_dbg_memblock {
@@ -653,7 +657,7 @@ struct pk_dbg_memblock {
struct pk_membucket *bkt;
};
static struct pk_dbg_memblock debug_all_allocs[1024 * 1024];
-static int64_t debug_alloc_head = 0;
+static size_t debug_alloc_head = 0;
static bool has_init_debug = false;
#endif
@@ -668,7 +672,7 @@ void
pk_memory_debug_print()
{
PK_LOGV_INF("Memory Manager printout:\nBucket count: %li\n", pk_bucket_head);
- for (long i = 0; i < pk_bucket_head; ++i) {
+ for (size_t i = 0; i < pk_bucket_head; ++i) {
PK_LOGV_INF("- bucket #%li\n", i);
PK_LOGV_INF("\tdescription: %s\n", pk_buckets[i].description);
PK_LOGV_INF("\tsize: %li\n", pk_buckets[i].size);
@@ -677,12 +681,12 @@ pk_memory_debug_print()
PK_LOGV_INF("\tallocs: %li\n", pk_buckets[i].allocs);
PK_LOGV_INF("\tlastEmptyBlockIndex: %li\n", pk_buckets[i].lastEmptyBlockIndex);
PK_LOGV_INF("\tmaxBlockCount: %li\n", pk_buckets[i].maxBlockCount);
- PK_LOGV_INF("\tblocks: %p\n", pk_buckets[i].blocks);
- PK_LOGV_INF("\tptr: %p\n", pk_buckets[i].ptr);
+ PK_LOGV_INF("\tblocks: %p\n", (void *)pk_buckets[i].blocks);
+ PK_LOGV_INF("\tptr: %p\n", (void *)pk_buckets[i].ptr);
PK_LOGV_INF("\ttransient: %i\n", pk_buckets[i].transient);
#ifdef PK_MEMORY_DEBUGGER
uint64_t count = 0;
- for (int64_t d = 0; d < debug_alloc_head; ++d) {
+ for (size_t d = 0; d < debug_alloc_head; ++d) {
if (debug_all_allocs[d].bkt == &pk_buckets[d] && debug_all_allocs[d].blk.size > 0) {
count += 1;
}
@@ -741,7 +745,7 @@ pk_bucket_create_inner(int64_t sz, bool transient, const char* description)
memset(bkt->blocks, 0, sz);
#endif
bkt->ptr = ((char*)(bkt->blocks)) + (sizeof(struct pk_memblock) * bkt->maxBlockCount);
- size_t misalignment = (uint64_t)(bkt->ptr) % PK_MAXIMUM_ALIGNMENT;
+ size_t misalignment = (size_t)(bkt->ptr) % PK_MAXIMUM_ALIGNMENT;
if (misalignment != 0) {
size_t moreBlocks = misalignment / sizeof(struct pk_memblock);
bkt->maxBlockCount += moreBlocks;
@@ -764,7 +768,7 @@ pk_bucket_create(const char* description, int64_t sz, bool transient)
void
pk_bucket_destroy(struct pk_membucket* bkt)
{
- int64_t i;
+ size_t i;
for (i = 0; i < pk_bucket_head; ++i) {
if (&pk_buckets[i] == bkt) {
if (pk_bucket_head == i + 1)
@@ -777,14 +781,16 @@ pk_bucket_destroy(struct pk_membucket* bkt)
bkt->head = 0;
bkt->lostBytes = 0;
bkt->allocs = 0;
- bkt->lastEmptyBlockIndex = -1;
+ bkt->lastEmptyBlockIndex = 0;
bkt->maxBlockCount = 0;
bkt->blocks = CAFE_BABE(struct pk_memblock);
bkt->ptr = CAFE_BABE(char);
bkt->transient = false;
mtx_destroy(&bkt->mtx);
#ifdef PK_MEMORY_DEBUGGER
- for (i = debug_alloc_head; i > -1; --i) {
+ size_t ii;
+ for (ii = debug_alloc_head+1; ii > 0; --ii) {
+ i = ii-1;
if (debug_all_allocs[i].bkt == bkt) {
debug_all_allocs[i].blk.data = NULL;
debug_all_allocs[i].blk.size = 0u;
@@ -840,7 +846,9 @@ pk_bucket_insert_block(struct pk_membucket* bkt, const struct pk_memblock* block
void
pk_bucket_collapse_empty_blocks(struct pk_membucket* bkt) {
- for (int64_t i = bkt->lastEmptyBlockIndex; i > -1; --i) {
+ size_t i, ii;
+ for (ii = bkt->lastEmptyBlockIndex+1; ii > 0; --ii) {
+ i = ii-1;
struct pk_memblock* block = &bkt->blocks[i];
if (block->size == 0 && i == bkt->lastEmptyBlockIndex) {
block->data = nullptr;
@@ -850,7 +858,7 @@ pk_bucket_collapse_empty_blocks(struct pk_membucket* bkt) {
if (block->size > 0) {
continue;
}
- for (int64_t k = i; k < bkt->lastEmptyBlockIndex; ++k) {
+ for (size_t k = i; k < bkt->lastEmptyBlockIndex; ++k) {
bkt->blocks[k].data = bkt->blocks[k + 1].data;
bkt->blocks[k].size = bkt->blocks[k + 1].size;
}
@@ -865,6 +873,7 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt)
return malloc(sz);
#endif
if (sz == 0) return nullptr;
+ size_t i;
size_t calculatedAlignment = alignment < PK_MINIMUM_ALIGNMENT ? PK_MINIMUM_ALIGNMENT : alignment;
size_t misalignment = 0;
struct pk_memblock* prevBlock = nullptr;
@@ -872,7 +881,7 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt)
struct pk_memblock* nextBlock = nullptr;
void* data = nullptr;
mtx_lock(&bkt->mtx);
- for (int64_t i = 0; i <= bkt->lastEmptyBlockIndex; ++i) {
+ for (i = 0; i <= bkt->lastEmptyBlockIndex; ++i) {
struct pk_memblock* blk = &bkt->blocks[i];
misalignment = (size_t)(blk->data) % calculatedAlignment;
misalignment = (calculatedAlignment - misalignment) % calculatedAlignment;
@@ -895,7 +904,7 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt)
#ifdef PK_MEMORY_DEBUGGER
bool handled = bkt->transient;
if (handled == false) {
- for (int64_t i = 0; i < debug_alloc_head; ++i) {
+ for (i = 0; i < debug_alloc_head; ++i) {
struct pk_dbg_memblock* mb = &debug_all_allocs[i];
if (mb->bkt != NULL) continue;
assert((mb->blk.size == 0 || (void*)(mb->blk.data) != data) && "mem address alloc'd twice!");
@@ -909,13 +918,10 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt)
}
}
if (handled == false) {
- debug_all_allocs[debug_alloc_head++] = (struct pk_dbg_memblock){
- .blk = (struct pk_memblock) {
- .data = (char*)(data),
- .size = sz,
- },
- .bkt = bkt,
- };
+ i = debug_alloc_head++;
+ debug_all_allocs[i].blk.data = (char*)data;
+ debug_all_allocs[i].blk.size = sz;
+ debug_all_allocs[i].bkt = bkt;
}
#endif
int64_t afterSize = block->size - (misalignment + sz);
@@ -948,11 +954,11 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt)
if (!bkt->transient) {
int64_t debug_tracked_alloc_size = 0;
int64_t debug_bucket_alloc_size = bkt->size - (sizeof(struct pk_memblock) * bkt->maxBlockCount);
- for (int64_t i = 0; i < debug_alloc_head; ++i) {
+ for (i = 0; i < debug_alloc_head; ++i) {
if (debug_all_allocs[i].bkt != bkt) continue;
debug_tracked_alloc_size += debug_all_allocs[i].blk.size;
}
- for (int64_t i = 0; i <= bkt->lastEmptyBlockIndex; ++i) {
+ for (i = 0; i <= bkt->lastEmptyBlockIndex; ++i) {
debug_bucket_alloc_size -= bkt->blocks[i].size;
}
assert(debug_tracked_alloc_size == debug_bucket_alloc_size && "allocation size mismatch!");
@@ -966,7 +972,7 @@ void*
pk_new_base(size_t sz, size_t alignment)
{
struct pk_membucket* bkt = nullptr;
- for (long i = 0; i < pk_bucket_head; ++i) {
+ for (size_t i = 0; i < pk_bucket_head; ++i) {
if (pk_buckets[i].transient == false && pk_buckets[i].size - pk_buckets[i].head > sz + PK_MAXIMUM_ALIGNMENT) {
bkt = &pk_buckets[i];
break;
@@ -991,13 +997,16 @@ pk_delete_bkt(const void* ptr, size_t sz, struct pk_membucket* bkt)
#ifdef PK_MEMORY_FORCE_MALLOC
return std::free(const_cast<void*>(ptr));
#endif
+ size_t i;
mtx_lock(&bkt->mtx);
assert(ptr >= bkt->raw && (char*)ptr < bkt->ptr + bkt->size && "pointer not in memory bucket range");
assert(sz > 0 && "attempted to free pointer of size 0");
#ifdef PK_MEMORY_DEBUGGER
+ size_t ii;
bool found = bkt->transient;
if (found == false) {
- for (int64_t i = debug_alloc_head - 1; i > -1; --i) {
+ for (ii = debug_alloc_head; ii > 0; --ii) {
+ i = ii-1;
struct pk_dbg_memblock* mb = &debug_all_allocs[i];
if (mb->bkt != bkt) continue;
if (mb->blk.size == 0) continue;
@@ -1026,7 +1035,7 @@ pk_delete_bkt(const void* ptr, size_t sz, struct pk_membucket* bkt)
char* afterPtr = ((char*)(ptr))+sz;
struct pk_memblock* beforeBlk = nullptr;
struct pk_memblock* afterBlk = nullptr;
- for (int64_t i = bkt->lastEmptyBlockIndex; i > 0; --i) {
+ for (i = bkt->lastEmptyBlockIndex; i > 0; --i) {
if (bkt->blocks[i-1].data + bkt->blocks[i-1].size == ptr) {
beforeBlk = &bkt->blocks[i-1];
}
@@ -1067,11 +1076,11 @@ pk_delete_bkt(const void* ptr, size_t sz, struct pk_membucket* bkt)
if (!bkt->transient) {
int64_t debug_tracked_alloc_size = 0;
int64_t debug_bucket_alloc_size = bkt->size - (sizeof(struct pk_memblock) * bkt->maxBlockCount);
- for (int64_t i = 0; i < debug_alloc_head; ++i) {
+ for (i = 0; i < debug_alloc_head; ++i) {
if (debug_all_allocs[i].bkt != bkt) continue;
debug_tracked_alloc_size += debug_all_allocs[i].blk.size;
}
- for (int64_t i = 0; i <= bkt->lastEmptyBlockIndex; ++i) {
+ for (i = 0; i <= bkt->lastEmptyBlockIndex; ++i) {
debug_bucket_alloc_size -= bkt->blocks[i].size;
}
assert(debug_tracked_alloc_size == debug_bucket_alloc_size && "allocation size mismatch!");
@@ -1084,7 +1093,7 @@ void
pk_delete_base(const void* ptr, size_t sz)
{
struct pk_membucket* bkt = nullptr;
- for (long i = 0; i < pk_bucket_head; ++i) {
+ for (size_t i = 0; i < pk_bucket_head; ++i) {
bkt = &pk_buckets[i];
if (ptr >= bkt->raw && (char*)ptr < bkt->ptr + bkt->size) break;
}
@@ -1095,8 +1104,12 @@ pk_delete_base(const void* ptr, size_t sz)
void
pk_delete(const void* ptr, size_t sz, struct pk_membucket* bkt)
{
- if (bkt != NULL) return pk_delete_bkt(ptr, sz, bkt);
- return pk_delete_base(ptr, sz);
+ if (bkt != NULL) {
+ pk_delete_bkt(ptr, sz, bkt);
+ return;
+ }
+ pk_delete_base(ptr, sz);
+ return;
}
#endif /* PK_IMPL_MEM */
@@ -1132,41 +1145,41 @@ int pk_compare_cstr(const struct pk_cstr *lhs, const struct pk_cstr *rhs);
struct pk_str
cstring_to_pk_str(char *s)
{
- return (struct pk_str) {
- .val = s,
- .length = (uint32_t)(strlen(s)),
- .reserved = 0,
- };
+ struct pk_str ret;
+ ret.val = s;
+ ret.length = (uint32_t)(strlen(s));
+ ret.reserved = 0;
+ return ret;
}
struct pk_cstr
cstring_to_pk_cstr(const char *s)
{
- return (struct pk_cstr) {
- .val = s,
- .length = (uint32_t)(strlen(s)),
- .reserved = 0,
- };
+ struct pk_cstr ret;
+ ret.val = s;
+ ret.length = (uint32_t)(strlen(s));
+ ret.reserved = 0;
+ return ret;
}
struct pk_str
pk_cstr_to_pk_str(const struct pk_cstr *s)
{
- return (struct pk_str) {
- .val = (char *)(s->val),
- .length = s->length,
- .reserved = s->reserved,
- };
+ struct pk_str ret;
+ ret.val = (char *)s->val;
+ ret.length = s->length;
+ ret.reserved = s->reserved;
+ return ret;
}
struct pk_cstr
pk_str_to_pk_cstr(const struct pk_str *s)
{
- return (struct pk_cstr) {
- .val = (char *)(s->val),
- .length = s->length,
- .reserved = s->reserved,
- };
+ struct pk_cstr ret;
+ ret.val = (char *)s->val;
+ ret.length = s->length;
+ ret.reserved = s->reserved;
+ return ret;
}
int
@@ -1195,12 +1208,12 @@ void pk_ev_init();
// note: pk_ev_teardown() is NOT thread-safe
void pk_ev_teardown();
-const pk_ev_mgr_id_T pk_ev_create_mgr();
+pk_ev_mgr_id_T pk_ev_create_mgr();
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);
-const pk_ev_id_T pk_ev_register_ev(pk_ev_mgr_id_T evmgr, 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);
void pk_ev_emit(pk_ev_mgr_id_T evmgr, pk_ev_id_T evid, void *user_emit_data);
@@ -1278,7 +1291,7 @@ pk_ev_init()
void
pk_ev_teardown()
{
- int i;
+ long unsigned int i;
for (i = 0; i < pk_ev_mstr.rn_mgrs; ++i) {
if ((atomic_load(&pk_ev_mstr.rn_mgrs) & (1lu << i)) == 0) continue;
mtx_lock(&pk_ev_mstr.mtxs[i]);
@@ -1307,7 +1320,6 @@ pk_ev_inner_ev_mgr_create(uint64_t ev_count, uint64_t cb_count)
struct pk_ev_mgr *mgr = (struct pk_ev_mgr*)malloc(sz);
if (mgr == NULL) goto early_exit;
- memset(mgr, 0, sz);
mgr->ev = (struct pk_ev*)(((char *)mgr) + sizeof(struct pk_ev_mgr));
atomic_init(&mgr->rn_ev, ev_count);
atomic_init(&mgr->rn_cb, cb_count);
@@ -1337,7 +1349,7 @@ pk_ev_inner_ev_mgr_clone(struct pk_ev_mgr *old, struct pk_ev_mgr *mgr)
}
}
-const pk_ev_mgr_id_T
+pk_ev_mgr_id_T
pk_ev_create_mgr()
{
uint64_t i;
@@ -1373,14 +1385,13 @@ recreate:
void
pk_ev_destroy_mgr(pk_ev_mgr_id_T evmgr)
{
- assert(evmgr >= 0);
mtx_lock(&pk_ev_mstr.mtxs[evmgr]);
free(pk_ev_mstr.mgrs[evmgr]);
pk_ev_mstr.mgrs[evmgr] = NULL;
mtx_unlock(&pk_ev_mstr.mtxs[evmgr]);
}
-const pk_ev_id_T
+pk_ev_id_T
pk_ev_register_ev(pk_ev_mgr_id_T evmgr, void *user_ev_data)
{
assert(evmgr < 64);
@@ -1527,14 +1538,39 @@ pk_arr_move_to_back(struct pk_arr *arr, uint32_t index)
if (arr->next <= 1) return;
#ifdef PK_ARR_MOVE_IN_PLACE
uint32_t i, ii;
- uint8_t *target = (uint8_t *)pk_new(arr->stride, arr->alignment, arr->bkt);
- uint8_t *buffer = (uint8_t *)arr->data;
+ char *target = (char *)pk_new(arr->stride, arr->alignment, arr->bkt);
+ char *buffer = (char *)arr->data;
+ // copy bytes to temp buffer
for (ii = 0, i = arr->stride * index; ii < arr->stride; ++ii, ++i) {
target[ii] = buffer[i];
}
+ // shift everything forward
+ // arr->stride = 8
+ // arr->next = 2
+ // index = 0
+ //
+ // for (i = 0; i < 8; ++i) {
+ // b[i] = b[i + 8]
+ // }
+ // b[00] = b[08]
+ // b[01] = b[09]
+ // ...
+ // b[07] = b[15]
for (i = arr->stride * index; i < (arr->stride * (arr->next - 1)); ++i) {
buffer[i] = buffer[i + arr->stride];
}
+ // copy temp buffer back into arr
+ // arr->stride = 8
+ // arr->next = 2
+ // index = 0
+ //
+ // for (ii = 0, i = 8; ii < 8; ++ii, ++i) {
+ // b[i] = t[ii]
+ // }
+ // b[08] = t[00]
+ // b[09] = t[01]
+ // ...
+ // b[15] = t[07]
for (ii = 0, i = arr->stride * (arr->next - 1); ii < arr->stride; ++ii, ++i) {
buffer[i] = target[ii];
}
@@ -1585,8 +1621,20 @@ pk_arr_remove_at(struct pk_arr *arr, uint32_t index)
}
#ifdef PK_ARR_MOVE_IN_PLACE
uint32_t i;
- uint8_t *buffer = (uint8_t *)arr->data;
- for (i = arr->stride * index; i < (arr->stride * (arr->next - 1)); ++i) {
+ char *buffer = (char *)arr->data;
+ // shift everything forward
+ // arr->stride = 8
+ // arr->next = 3
+ // index = 0
+ //
+ // for (i = 0; i < 16; ++i) {
+ // b[i] = b[i + 8]
+ // }
+ // b[00] = b[08]
+ // b[01] = b[09]
+ // ...
+ // b[15] = b[23]
+ for (i = arr->stride * index; i < arr->stride * arr->next; ++i) {
buffer[i] = buffer[i + arr->stride];
}
#else