diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-01-14 13:57:35 -0500 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-01-14 13:57:35 -0500 |
| commit | 46d814de510d0a7753c3e49eed3b3440d1c7c681 (patch) | |
| tree | 91fef3ca83d1cced76bded305e0ead4f58a0d64d /src/pk.h | |
| parent | 28f25f4c82ef7e712bc0c22f9ccb054efa584275 (diff) | |
pk.h: update to 0.2.0
Diffstat (limited to 'src/pk.h')
| -rw-r--r-- | src/pk.h | 196 |
1 files changed, 122 insertions, 74 deletions
@@ -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 |
