summaryrefslogtreecommitdiff
path: root/src/vendor/pk.h
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-01-09 14:44:31 -0500
committerJonathan Bradley <jcb@pikum.xyz>2025-01-09 14:44:31 -0500
commitb76e309166f714b0a66fb4802f02e92a82d09082 (patch)
tree44244fc0e6f873e1ccf6e1e95e2fec62fcec394a /src/vendor/pk.h
parentb04fefe8ee0086bc1404c06b8351ecb4e942f151 (diff)
flatten file structure + rename
Diffstat (limited to 'src/vendor/pk.h')
-rw-r--r--src/vendor/pk.h1246
1 files changed, 0 insertions, 1246 deletions
diff --git a/src/vendor/pk.h b/src/vendor/pk.h
deleted file mode 100644
index 8d788d1..0000000
--- a/src/vendor/pk.h
+++ /dev/null
@@ -1,1246 +0,0 @@
-#ifndef PK_SINGLE_HEADER_FILE_H
-#define PK_SINGLE_HEADER_FILE_H
-/******************************************************************************
-* PK Single-Header-Library V0.0.2
-*
-* Author: Jonathan Bradley
-* Copyright: © 2024-2024 Jonathan Bradley
-* Description:
-*
-*******************************************************************************
-* pkmacros.h:
-*
-*******************************************************************************
-* pkmem-types.h:
-*
-*******************************************************************************
-* pkmem.h:
-*
-*******************************************************************************
-* pkstr.h:
-*
-*******************************************************************************
-* pkev.h:
-*
-******************************************************************************/
-
-#define PK_VERSION "0.0.2"
-
-#ifdef PK_IMPL_ALL
-# ifndef PK_IMPL_MEM_TYPES
-# define PK_IMPL_MEM_TYPES
-# endif
-# ifndef PK_IMPL_MEM
-# define PK_IMPL_MEM
-# endif
-# ifndef PK_IMPL_STR
-# define PK_IMPL_STR
-# endif
-# ifndef PK_IMPL_EV
-# define PK_IMPL_EV
-# endif
-#endif
-#ifndef PK_MACROS_H
-#define PK_MACROS_H
-
-#ifndef PK_LOG_OVERRIDE
-# ifdef NDEBUG
-# define PK_LOG_ERR(str) (void)str
-# define PK_LOG_INF(str) (void)str
-# 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_LOGV_ERR(str, ...) fprintf(stderr, str, __VA_ARGS__)
-# define PK_LOGV_INF(str, ...) fprintf(stdout, str, __VA_ARGS__)
-# endif
-#endif
-
-#define PK_Q(x) #x
-#define PK_QUOTE(x) PK_Q(x)
-#define PK_CONCAT2(x, y) x##y
-#define PK_CONCAT(x, y) PK_CONCAT2(x, y)
-
-#define PK_HAS_FLAG(val, flag) ((val & flag) == flag)
-#define PK_CLAMP(val, min, max) (val < min ? min : val > max ? max : val)
-#define PK_MIN(val, min) (val < min ? val : min)
-#define PK_MAX(val, max) (val > max ? val : max)
-
-#define PK_TO_BIN_PAT PK_Q(%c%c%c%c%c%c%c%c)
-#define PK_TO_BIN_PAT_8 PK_TO_BIN_PAT
-#define PK_TO_BIN_PAT_16 PK_TO_BIN_PAT PK_TO_BIN_PAT
-#define PK_TO_BIN_PAT_32 PK_TO_BIN_PAT_16 PK_TO_BIN_PAT_16
-#define PK_TO_BIN_PAT_64 PK_TO_BIN_PAT_32 PK_TO_BIN_PAT_32
-#define PK_TO_BIN(byte) \
- ((byte) & 0x80 ? '1' : '0'), \
- ((byte) & 0x40 ? '1' : '0'), \
- ((byte) & 0x20 ? '1' : '0'), \
- ((byte) & 0x10 ? '1' : '0'), \
- ((byte) & 0x08 ? '1' : '0'), \
- ((byte) & 0x04 ? '1' : '0'), \
- ((byte) & 0x02 ? '1' : '0'), \
- ((byte) & 0x01 ? '1' : '0')
-#define PK_TO_BIN_8(u8) PK_TO_BIN(u8)
-#define PK_TO_BIN_16(u16) PK_TO_BIN((u16 >> 8)), PK_TO_BIN(u16 & 0x00FF)
-#define PK_TO_BIN_32(u32) PK_TO_BIN_16((u32 >> 16)), PK_TO_BIN_16(u32 & 0x0000FFFF)
-#define PK_TO_BIN_64(u64) PK_TO_BIN_32((u64 >> 32)), PK_TO_BIN_32(u64 & 0x00000000FFFFFFFF)
-
-#if defined(__cplusplus)
-# define CAFE_BABE(T) reinterpret_cast<T *>(0xCAFEBABE)
-#else
-# define CAFE_BABE(T) (T *)(0xCAFEBABE)
-#endif
-
-#define NULL_CHAR_ARR(v, len) char v[len]; v[0] = '\0'; v[len-1] = '\0';
-
-#define IS_CONSTRUCTIBLE(T) constexpr(std::is_default_constructible<T>::value && !std::is_integral<T>::value && !std::is_floating_point<T>::value)
-#define IS_DESTRUCTIBLE(T) constexpr(std::is_destructible<T>::value && !std::is_integral<T>::value && !std::is_floating_point<T>::value && !std::is_array<T>::value)
-
-#define TypeSafeInt2_H(TypeName, Type, Max, TypeName_T, TypeName_MAX, TypeName_T_MAX) \
- using TypeName_T = Type; \
- enum class TypeName : TypeName_T; \
- constexpr TypeName_T TypeName_T_MAX = TypeName_T{Max}; \
- constexpr TypeName TypeName_MAX = TypeName{TypeName_T_MAX}; \
- TypeName operator+(const TypeName& a, const TypeName& b); \
- TypeName operator-(const TypeName& a, const TypeName& b); \
- TypeName operator&(const TypeName& a, const TypeName& b); \
- TypeName operator|(const TypeName& a, const TypeName& b); \
- TypeName operator^(const TypeName& a, const TypeName& b); \
- TypeName& operator++(TypeName& a); \
- TypeName& operator--(TypeName& a); \
- TypeName operator++(TypeName& a, int); \
- TypeName operator--(TypeName& a, int); \
- TypeName operator<<(const TypeName& a, const TypeName& b); \
- TypeName operator>>(const TypeName& a, const TypeName& b); \
- TypeName operator+=(TypeName& a, const TypeName& b); \
- TypeName operator-=(TypeName& a, const TypeName& b); \
- TypeName operator&=(TypeName& a, const TypeName& b); \
- TypeName operator|=(TypeName& a, const TypeName& b); \
- TypeName operator^=(TypeName& a, const TypeName& b); \
- TypeName operator~(TypeName& a);
-#define TypeSafeInt2_B(TypeName, TypeName_T) \
- inline TypeName operator+(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) + static_cast<TypeName_T>(b)); \
- } \
- inline TypeName operator-(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) - static_cast<TypeName_T>(b)); \
- } \
- inline TypeName operator&(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) & static_cast<TypeName_T>(b)); \
- } \
- inline TypeName operator|(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) | static_cast<TypeName_T>(b)); \
- } \
- inline TypeName operator^(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) ^ static_cast<TypeName_T>(b)); \
- } \
- inline TypeName& operator++(TypeName& a) { \
- a = a + TypeName{1}; \
- return a; \
- } \
- inline TypeName& operator--(TypeName& a) { \
- a = a - TypeName{1}; \
- return a; \
- }; \
- inline TypeName operator++(TypeName& a, int) { \
- a = a + TypeName{1}; \
- return a; \
- } \
- inline TypeName operator--(TypeName& a, int) { \
- a = a - TypeName{1}; \
- return a; \
- }; \
- inline TypeName operator<<(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) << static_cast<TypeName_T>(b)); \
- }; \
- inline TypeName operator>>(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) >> static_cast<TypeName_T>(b)); \
- }; \
- inline TypeName operator+=(TypeName& a, const TypeName& b) { \
- a = TypeName{a + b}; \
- return a; \
- }; \
- inline TypeName operator-=(TypeName& a, const TypeName& b) { \
- a = TypeName{a - b}; \
- return a; \
- }; \
- inline TypeName operator&=(TypeName& a, const TypeName& b) { \
- a = TypeName{a & b}; \
- return a; \
- }; \
- inline TypeName operator|=(TypeName& a, const TypeName& b) { \
- a = TypeName{a | b}; \
- return a; \
- }; \
- inline TypeName operator^=(TypeName& a, const TypeName& b) { \
- a = TypeName{a ^ b}; \
- return a; \
- }; \
- inline TypeName operator~(TypeName& a) { \
- a = static_cast<TypeName>(~static_cast<TypeName_T>(a)); \
- return a; \
- };
-#define TypeSafeInt_H(TypeName, Type, Max) \
- TypeSafeInt2_H(TypeName, Type, Max, PK_CONCAT(TypeName, _T), PK_CONCAT(TypeName, _MAX), PK_CONCAT(TypeName, _T_MAX))
-#define TypeSafeInt_B(TypeName) \
- TypeSafeInt2_B(TypeName, PK_CONCAT(TypeName, _T))
-
-#define TypeSafeInt2_H_constexpr(TypeName, Type, Max, TypeName_T, TypeName_MAX, TypeName_T_MAX) \
- using TypeName_T = Type; \
- enum class TypeName : TypeName_T; \
- constexpr TypeName_T TypeName_T_MAX = TypeName_T{Max}; \
- constexpr TypeName TypeName_MAX = TypeName{TypeName_T_MAX}; \
- constexpr TypeName operator+(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) + static_cast<TypeName_T>(b)); \
- } \
- constexpr TypeName operator-(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) - static_cast<TypeName_T>(b)); \
- } \
- constexpr TypeName operator&(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) & static_cast<TypeName_T>(b)); \
- } \
- constexpr TypeName operator|(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) | static_cast<TypeName_T>(b)); \
- } \
- constexpr TypeName operator^(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) ^ static_cast<TypeName_T>(b)); \
- } \
- constexpr TypeName& operator++(TypeName& a) { \
- a = a + TypeName{1}; \
- return a; \
- } \
- constexpr TypeName& operator--(TypeName& a) { \
- a = a - TypeName{1}; \
- return a; \
- }; \
- constexpr TypeName operator++(TypeName& a, int) { \
- a = a + TypeName{1}; \
- return a; \
- } \
- constexpr TypeName operator--(TypeName& a, int) { \
- a = a - TypeName{1}; \
- return a; \
- }; \
- constexpr TypeName operator<<(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) << static_cast<TypeName_T>(b)); \
- }; \
- constexpr TypeName operator>>(const TypeName& a, const TypeName& b) { \
- return TypeName(static_cast<TypeName_T>(a) >> static_cast<TypeName_T>(b)); \
- }; \
- constexpr TypeName operator+=(TypeName& a, const TypeName& b) { \
- a = TypeName{a + b}; \
- return a; \
- }; \
- constexpr TypeName operator-=(TypeName& a, const TypeName& b) { \
- a = TypeName{a - b}; \
- return a; \
- }; \
- constexpr TypeName operator&=(TypeName& a, const TypeName& b) { \
- a = TypeName{a & b}; \
- return a; \
- }; \
- constexpr TypeName operator|=(TypeName& a, const TypeName& b) { \
- a = TypeName{a | b}; \
- return a; \
- }; \
- constexpr TypeName operator^=(TypeName& a, const TypeName& b) { \
- a = TypeName{a ^ b}; \
- return a; \
- }; \
- constexpr TypeName operator~(const TypeName& a) { \
- return static_cast<TypeName>(~static_cast<TypeName_T>(a)); \
- };
-#define TypeSafeInt_constexpr(TypeName, Type, Max) \
- TypeSafeInt2_H_constexpr(TypeName, Type, Max, PK_CONCAT(TypeName, _T), PK_CONCAT(TypeName, _MAX), PK_CONCAT(TypeName, _T_MAX))
-
-#endif /* PK_MACROS_H */
-#ifndef PK_MEM_TYPES_H
-#define PK_MEM_TYPES_H
-
-#include <stdint.h>
-
-typedef uint32_t pk_handle_bucket_index_T;
-typedef uint32_t pk_handle_item_index_T;
-
-enum PK_HANDLE_VALIDATION : uint8_t {
- PK_HANDLE_VALIDATION_VALID = 0,
- PK_HANDLE_VALIDATION_BUCKET_INDEX_TOO_HIGH = 1,
- PK_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH = 2,
- PK_HANDLE_VALIDATION_VALUE_MAX = 3,
-};
-
-struct pk_handle {
- pk_handle_bucket_index_T bucketIndex;
- pk_handle_item_index_T itemIndex;
-};
-
-#define PK_HANDLE_MAX ((struct pk_handle){ .bucketIndex = 0xFFFFFFFF, .itemIndex = 0xFFFFFFFF })
-
-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 };
-
-inline constexpr bool
-operator==(const pk_handle& lhs, const pk_handle& rhs)
-{
- return lhs.bucketIndex == rhs.bucketIndex && lhs.itemIndex == rhs.itemIndex;
-}
-
-template<const pk_handle handle, const pk_handle bucketHandle, const uint64_t maxItems>
-inline constexpr enum PK_HANDLE_VALIDATION
-pk_handle_validate_constexpr()
-{
- if constexpr (handle == pk_handle_MAX_constexpr)
- return PK_HANDLE_VALIDATION_VALUE_MAX;
- if constexpr (handle.bucketIndex > bucketHandle.bucketIndex)
- return PK_HANDLE_VALIDATION_BUCKET_INDEX_TOO_HIGH;
- if constexpr (handle.itemIndex > maxItems)
- return PK_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH;
- if constexpr (handle.bucketIndex == bucketHandle.bucketIndex && handle.itemIndex > bucketHandle.itemIndex)
- return PK_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH;
- return PK_HANDLE_VALIDATION_VALID;
-}
-#endif /* __cplusplus */
-
-struct pk_membucket;
-
-#endif /* PK_MEM_TYPES_H */
-
-#ifdef PK_IMPL_MEM_TYPES
-
-enum PK_HANDLE_VALIDATION
-pk_handle_validate(const struct pk_handle handle, const struct pk_handle bucketHandle, const uint64_t maxItems)
-{
- if (handle.bucketIndex == PK_HANDLE_MAX.bucketIndex && handle.itemIndex == PK_HANDLE_MAX.itemIndex)
- return PK_HANDLE_VALIDATION_VALUE_MAX;
- if (handle.bucketIndex > bucketHandle.bucketIndex)
- return PK_HANDLE_VALIDATION_BUCKET_INDEX_TOO_HIGH;
- if (handle.itemIndex > maxItems)
- return PK_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH;
- if (handle.bucketIndex == bucketHandle.bucketIndex && handle.itemIndex > bucketHandle.itemIndex)
- return PK_HANDLE_VALIDATION_ITEM_INDEX_TOO_HIGH;
- return PK_HANDLE_VALIDATION_VALID;
-}
-
-#endif /* PK_IMPL_MEM_TYPES */
-#ifndef PK_MEM_H
-#define PK_MEM_H
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifndef PK_DEFAULT_BUCKET_SIZE
-# define PK_DEFAULT_BUCKET_SIZE (1ULL * 1024ULL * 1024ULL * 256ULL)
-#endif
-#ifndef PK_MINIMUM_ALIGNMENT
-# define PK_MINIMUM_ALIGNMENT 1
-#endif
-#ifndef PK_MAXIMUM_ALIGNMENT
-# define PK_MAXIMUM_ALIGNMENT 64
-#endif
-
-struct pk_membucket* pk_bucket_create(const char* description, int64_t sz, bool transient);
-void pk_bucket_destroy(struct pk_membucket* bkt);
-void pk_bucket_reset(struct pk_membucket* bkt);
-
-void pk_memory_debug_print();
-void pk_memory_flush();
-void pk_memory_teardown_all();
-bool pk_memory_is_in_bucket(const void* ptr, const struct pk_membucket* bkt);
-
-void* pk_new_base(size_t sz, size_t alignment);
-void* pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt);
-void pk_delete_base(const void* ptr, size_t sz);
-void pk_delete_bkt(const void* ptr, size_t sz, struct pk_membucket* bkt);
-
-#if defined(__cplusplus)
-
-#include <type_traits>
-
-static inline void stupid_header_warnings_cpp() { (void)std::is_const<void>::value; }
-
-template <typename T>
-inline T*
-pk_new(pk_membucket* bucket = nullptr)
-{
- void* ptr = nullptr;
- if (bucket) {
- ptr = pk_new_bkt(sizeof(T), alignof(T), bucket);
- } else {
- ptr = pk_new_base(sizeof(T), alignof(T));
- }
- if IS_CONSTRUCTIBLE(T) {
- return new (ptr) T{};
- }
- return reinterpret_cast<T*>(ptr);
-}
-
-template <typename T>
-inline T*
-pk_new(long count, pk_membucket* bucket = nullptr)
-{
- char* ptr = nullptr;
- if (bucket) {
- ptr = static_cast<char*>(pk_new_bkt(sizeof(T) * count, alignof(T), bucket));
- } else {
- ptr = static_cast<char*>(pk_new_base(sizeof(T) * count, alignof(T)));
- }
- if IS_CONSTRUCTIBLE(T) {
- for (long i = 0; i < count; ++i) {
- new (ptr + (i * sizeof(T))) T{};
- }
- }
- return reinterpret_cast<T*>(ptr);
-}
-
-template <typename T>
-inline void
-pk_delete(const T* ptr, pk_membucket* bucket = nullptr)
-{
- if IS_DESTRUCTIBLE(T) {
- reinterpret_cast<const T*>(ptr)->~T();
- }
- if (bucket) {
- return pk_delete_bkt(static_cast<const void*>(ptr), sizeof(T), bucket);
- } else {
- return pk_delete_base(static_cast<const void*>(ptr), sizeof(T));
- }
-}
-
-template <typename T>
-inline void
-pk_delete(const T* ptr, long count, pk_membucket* bucket = nullptr)
-{
- if IS_DESTRUCTIBLE(T) {
- for (long i = 0; i < count; ++i) {
- reinterpret_cast<const T*>(reinterpret_cast<const char*>(ptr) + (i * sizeof(T)))->~T();
- }
- }
- if (bucket) {
- return pk_delete_bkt(static_cast<const void*>(ptr), sizeof(T) * count, bucket);
- } else {
- return pk_delete_base(static_cast<const void*>(ptr), sizeof(T) * count);
- }
-}
-
-#endif /* __cplusplus */
-
-#endif /* PK_MEM */
-
-#ifdef PK_IMPL_MEM
-
-#include <string.h>
-#include <stdio.h>
-#include <threads.h>
-#include <assert.h>
-
-static inline void pkmem_stupid_header_warnings() { (void)stdout; }
-
-#if defined(PK_MEMORY_DEBUGGER)
-/*
- * Note that certain aspects of this expect that you only have one non-transient bucket.
- * If you need to track multiple non-transient buckets, these sections will need a refactor.
- */
-#endif
-
-struct pk_memblock {
- char* data;
- size_t size;
-};
-
-struct pk_membucket {
- // the total size of the bucket, `blocks+ptr`
- int64_t size;
- // the current head of the bucket: byte offset from `ptr`.
- // All currently alloc'd data is before this offset
- int64_t head;
- // amount of lost bytes in this membucket, hopefully zero
- int64_t lostBytes;
- // the number of active allocations from this bucket
- int64_t allocs;
- // the index of the last empty block.
- // Should always point to `pk_memblock{ .data = ptr+head, .size=size-head }`
- int64_t lastEmptyBlockIndex;
- // number of pk_memblocks in the `*blocks` array
- int64_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
- union {
- char* ptr;
- void* raw;
- };
- const char* description;
- mtx_t mtx;
- bool transient;
-};
-
-static struct pk_membucket pk_buckets[8];
-static int64_t pk_bucket_head = 0;
-
-#ifdef PK_MEMORY_DEBUGGER
-struct pk_dbg_memblock {
- struct pk_memblock blk;
- struct pk_membucket *bkt;
-};
-static struct pk_dbg_memblock debug_all_allocs[1024 * 1024];
-static int64_t debug_alloc_head = 0;
-static bool has_init_debug = false;
-#endif
-
-bool
-pk_memory_is_in_bucket(const void* ptr, const struct pk_membucket* bkt)
-{
- if (ptr >= bkt->raw && (const char*)ptr < bkt->ptr + bkt->size) return true;
- return false;
-}
-
-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) {
- 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);
- PK_LOGV_INF("\thead: %li\n", pk_buckets[i].head);
- PK_LOGV_INF("\tlostBytes: %li\n", pk_buckets[i].lostBytes);
- 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("\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) {
- if (debug_all_allocs[d].bkt == &pk_buckets[d] && debug_all_allocs[d].blk.size > 0) {
- count += 1;
- }
- }
- PK_LOGV_INF("\tdebug alloc count: %lu\n", count);
- PK_LOGV_INF("\tdebug alloc last: %lu\n", debug_alloc_head);
-#endif
- }
-}
-
-void
-pk_memory_flush()
-{
- for (long i = pk_bucket_head - 2; i > -1; --i) {
- if (pk_buckets[i].head != 0) break;
- if (pk_buckets[i+1].head != 0) break;
- if (pk_buckets[i].transient == true) break;
- if (pk_buckets[i+1].transient == true) break;
- pk_bucket_head--;
- pk_bucket_destroy(&pk_buckets[i + 1]);
- }
-}
-
-void
-pk_memory_teardown_all()
-{
- for (int64_t i = pk_bucket_head - 1; i > 0; --i) {
- if (pk_buckets[i].ptr == nullptr) continue;
- pk_bucket_destroy(&pk_buckets[i]);
- }
- pk_bucket_head = 0;
-}
-
-static int64_t
-pk_bucket_create_inner(int64_t sz, bool transient, const char* description)
-{
-#ifdef PK_MEMORY_DEBUGGER
- if (has_init_debug == false) {
- has_init_debug = true;
- memset(debug_all_allocs, 0, sizeof(struct pk_dbg_memblock) * 1024 * 1024);
- }
-#endif
- int64_t blockCount = sz * 0.01;
- struct pk_membucket* bkt = &pk_buckets[pk_bucket_head];
- bkt->size = sz;
- bkt->head = 0;
- bkt->lostBytes = 0;
- bkt->allocs = 0;
- bkt->lastEmptyBlockIndex = 0;
- bkt->maxBlockCount = blockCount < 10 ? 10 : blockCount;
- bkt->blocks = (struct pk_memblock*)malloc(sz);
- assert(bkt->blocks != nullptr && "failed to allocate memory");
-#if 1
- 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;
- if (misalignment != 0) {
- size_t moreBlocks = misalignment / sizeof(struct pk_memblock);
- bkt->maxBlockCount += moreBlocks;
- bkt->ptr += (PK_MAXIMUM_ALIGNMENT - misalignment);
- }
- bkt->description = description;
- bkt->transient = transient;
- struct pk_memblock* memBlock = (struct pk_memblock*)(bkt->blocks);
- memBlock->data = bkt->ptr;
- memBlock->size = sz - (sizeof(struct pk_memblock) * bkt->maxBlockCount);
- return pk_bucket_head++;
-}
-
-struct pk_membucket*
-pk_bucket_create(const char* description, int64_t sz, bool transient)
-{
- return &pk_buckets[pk_bucket_create_inner(sz, transient, description)];
-}
-
-void
-pk_bucket_destroy(struct pk_membucket* bkt)
-{
- int64_t i;
- for (i = 0; i < pk_bucket_head; ++i) {
- if (&pk_buckets[i] == bkt) {
- if (pk_bucket_head == i)
- pk_bucket_head--;
- break;
- }
- }
- free(bkt->blocks);
- bkt->size = 0;
- bkt->head = 0;
- bkt->lostBytes = 0;
- bkt->allocs = 0;
- bkt->lastEmptyBlockIndex = -1;
- bkt->maxBlockCount = 0;
- bkt->blocks = CAFE_BABE(struct pk_memblock);
- bkt->ptr = CAFE_BABE(char);
- bkt->transient = false;
-#ifdef PK_MEMORY_DEBUGGER
- for (i = debug_alloc_head; i > -1; --i) {
- if (debug_all_allocs[i].bkt == bkt) {
- debug_all_allocs[i].blk.data = NULL;
- debug_all_allocs[i].blk.size = 0u;
- }
- }
-#endif
-}
-
-void
-pk_bucket_reset(struct pk_membucket* bkt)
-{
- int64_t i;
- if (bkt->transient != true) {
- PK_LOG_ERR("WARNING: pk_bucket_reset called on non-transient pk_membucket\n");
- }
- bkt->head = 0;
- bkt->lostBytes = 0;
- bkt->allocs = 0;
- bkt->lastEmptyBlockIndex = 0;
- bkt->blocks->data = bkt->ptr;
- bkt->blocks->size = bkt->size - (sizeof(struct pk_memblock) * bkt->maxBlockCount);
-#ifdef PK_MEMORY_DEBUGGER
- for (i = debug_alloc_head; i > -1; --i) {
- if (debug_all_allocs[i].bkt == bkt) {
- debug_all_allocs[i].blk.data = NULL;
- debug_all_allocs[i].blk.size = 0u;
- }
- }
-#endif
-}
-
-void
-pk_bucket_insert_block(struct pk_membucket* bkt, const struct pk_memblock* block)
-{
- int64_t index = bkt->lastEmptyBlockIndex;
- while (index >= 0) {
- struct pk_memblock* b = &bkt->blocks[index];
- struct pk_memblock* nb = &bkt->blocks[index + 1];
- if (b->data < block->data) {
- break;
- }
- nb->data = b->data;
- nb->size = b->size;
- index -= 1;
- }
- struct pk_memblock *b = &bkt->blocks[index + 1];
- b->data = block->data;
- b->size = block->size;
- bkt->lastEmptyBlockIndex += 1;
-}
-
-void
-pk_bucket_collapse_empty_blocks(struct pk_membucket* bkt) {
- for (int64_t i = bkt->lastEmptyBlockIndex; i > -1; --i) {
- struct pk_memblock* block = &bkt->blocks[i];
- if (block->size == 0 && i == bkt->lastEmptyBlockIndex) {
- block->data = nullptr;
- bkt->lastEmptyBlockIndex -= 1;
- continue;
- }
- if (block->size > 0) {
- continue;
- }
- for (int64_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;
- }
- bkt->lastEmptyBlockIndex -= 1;
- }
-}
-
-void*
-pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt)
-{
-#ifdef PK_MEMORY_FORCE_MALLOC
- return malloc(sz);
-#endif
- if (sz == 0) return nullptr;
- size_t calculatedAlignment = alignment < PK_MINIMUM_ALIGNMENT ? PK_MINIMUM_ALIGNMENT : alignment;
- size_t misalignment = 0;
- struct pk_memblock* prevBlock = nullptr;
- struct pk_memblock* block = nullptr;
- struct pk_memblock* nextBlock = nullptr;
- void* data = nullptr;
- mtx_lock(&bkt->mtx);
- for (int64_t i = 0; i <= bkt->lastEmptyBlockIndex; ++i) {
- struct pk_memblock* blk = &bkt->blocks[i];
- misalignment = (size_t)(blk->data) % calculatedAlignment;
- misalignment = (calculatedAlignment - misalignment) % calculatedAlignment;
- if (blk->size >= sz + misalignment) {
- block = blk;
- if (i < bkt->lastEmptyBlockIndex && bkt->blocks[i + 1].data == block->data + block->size) {
- nextBlock = &bkt->blocks[i + 1];
- }
- if (i > 0 && i != bkt->lastEmptyBlockIndex && (bkt->blocks[i-1].data + bkt->blocks[i-1].size) == block->data) {
- prevBlock = &bkt->blocks[i - 1];
- }
- break;
- }
- }
- assert(block != nullptr && "memory corruption: failed to find bucket with enough space");
- data = block->data + misalignment;
-#ifdef PK_MEMORY_DEBUGGER
- bool handled = bkt->transient;
- if (handled == false) {
- for (int64_t 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!");
- if (mb->blk.size == 0) {
- mb->blk.data = (char*)(data);
- mb->blk.size = sz;
- mb->bkt = bkt;
- handled = true;
- break;
- }
- }
- }
- if (handled == false) {
- debug_all_allocs[debug_alloc_head++] = (struct pk_dbg_memblock){
- .blk = (struct pk_memblock) {
- .data = (char*)(data),
- .size = sz,
- },
- .bkt = bkt,
- };
- }
-#endif
- int64_t afterSize = block->size - (misalignment + sz);
- if (block->data == bkt->ptr + bkt->head) {
- bkt->head += (sz + misalignment);
- }
- if (afterSize > 0 && nextBlock == nullptr) {
- struct pk_memblock newBlock;
- memset(&newBlock, 0, sizeof(struct pk_memblock));
- newBlock.data = block->data + misalignment + sz;
- newBlock.size = afterSize;
- pk_bucket_insert_block(bkt, &newBlock);
- }
- if (prevBlock == nullptr && nextBlock == nullptr) {
- block->size = misalignment;
- } else if (nextBlock != nullptr) {
- block->size = misalignment;
- nextBlock->data -= afterSize;
- nextBlock->size += afterSize;
- } else if (prevBlock != nullptr) {
- prevBlock->size += misalignment;
- block->data += misalignment + sz;
- block->size = 0; // if you make it here, afterSize has already been handled
- }
- bkt->allocs++;
- assert(data >= bkt->raw && "allocated data is before bucket data");
- assert((char*)data <= bkt->ptr + bkt->size && "allocated data is after bucket data");
- pk_bucket_collapse_empty_blocks(bkt);
-#ifdef PK_MEMORY_DEBUGGER
- 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) {
- 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) {
- debug_bucket_alloc_size -= bkt->blocks[i].size;
- }
- assert(debug_tracked_alloc_size == debug_bucket_alloc_size && "allocation size mismatch!");
- }
-#endif
- mtx_unlock(&bkt->mtx);
- return data;
-}
-
-void*
-pk_new_base(size_t sz, size_t alignment)
-{
- struct pk_membucket* bkt = nullptr;
- for (long 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;
- }
- }
- if (bkt == nullptr) {
- bkt = &pk_buckets[pk_bucket_create_inner(PK_DEFAULT_BUCKET_SIZE, false, "pk_bucket internally created")];
- }
- return pk_new_bkt(sz, alignment, bkt);
-}
-
-void
-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
- 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
- bool found = bkt->transient;
- if (found == false) {
- for (int64_t i = debug_alloc_head - 1; i > -1; --i) {
- struct pk_dbg_memblock* mb = &debug_all_allocs[i];
- if (mb->bkt != bkt) continue;
- if (mb->blk.size == 0) continue;
- if ((void*)(mb->blk.data) == ptr) {
- assert(mb->blk.size == sz && "[PK_MEMORY_HPP] incorrect free size");
- mb->blk.size = 0;
- mb->bkt = NULL;
- found = true;
- if (i == (debug_alloc_head - 1)) {
- debug_alloc_head--;
- }
- break;
- }
- }
- }
- assert(found && "[PK_MEMORY_HPP] double free or invalid ptr");
-#endif
- bkt->allocs--;
- if (bkt->allocs == 0) {
- bkt->head = 0;
- bkt->lastEmptyBlockIndex = 0;
- bkt->blocks[0].data = bkt->ptr;
- bkt->blocks[0].size = bkt->size - (sizeof(struct pk_memblock) * bkt->maxBlockCount);
- return;
- }
- char* afterPtr = ((char*)(ptr))+sz;
- struct pk_memblock* beforeBlk = nullptr;
- struct pk_memblock* afterBlk = nullptr;
- for (int64_t i = bkt->lastEmptyBlockIndex; i > 0; --i) {
- if (bkt->blocks[i-1].data + bkt->blocks[i-1].size == ptr) {
- beforeBlk = &bkt->blocks[i-1];
- }
- if (bkt->blocks[i].data == afterPtr) {
- afterBlk = &bkt->blocks[i];
- break;
- }
- if (bkt->blocks[i-1].data < (char*)ptr) {
- break;
- }
- }
- if (ptr == bkt->ptr && afterBlk == nullptr && bkt->blocks[0].data == afterPtr) {
- afterBlk = &bkt->blocks[0];
- }
- if (afterBlk != nullptr && afterBlk->data == bkt->ptr + bkt->head) {
- bkt->head -= sz;
- if (beforeBlk != nullptr) {
- bkt->head -= beforeBlk->size;
- }
- }
- if (beforeBlk == nullptr && afterBlk == nullptr) {
- struct pk_memblock newBlock;
- memset(&newBlock, 0, sizeof(struct pk_memblock));
- newBlock.data = (char*)ptr;
- newBlock.size = sz;
- pk_bucket_insert_block(bkt, &newBlock);
- } else if (beforeBlk != nullptr && afterBlk != nullptr) {
- beforeBlk->size += sz + afterBlk->size;
- afterBlk->size = 0;
- } else if (beforeBlk != nullptr) {
- beforeBlk->size += sz;
- } else if (afterBlk != nullptr) {
- afterBlk->data -= sz;
- afterBlk->size += sz;
- }
- pk_bucket_collapse_empty_blocks(bkt);
-#ifdef PK_MEMORY_DEBUGGER
- 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) {
- 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) {
- debug_bucket_alloc_size -= bkt->blocks[i].size;
- }
- assert(debug_tracked_alloc_size == debug_bucket_alloc_size && "allocation size mismatch!");
- }
-#endif
- mtx_unlock(&bkt->mtx);
-}
-
-void
-pk_delete_base(const void* ptr, size_t sz)
-{
- struct pk_membucket* bkt = nullptr;
- for (long i = 0; i < pk_bucket_head; ++i) {
- bkt = &pk_buckets[i];
- if (ptr >= bkt->raw && (char*)ptr < bkt->ptr + bkt->size) break;
- }
- assert(bkt != nullptr && "failed to determine correct memory bucket");
- pk_delete_bkt(ptr, sz, bkt);
-}
-
-#endif /* PK_IMPL_MEM */
-#ifndef PK_STR_H
-#define PK_STR_H
-
-#include <stdint.h>
-
-struct pk_str {
- char *val;
- uint32_t length;
- uint32_t reserved;
-};
-struct pk_cstr {
- const char *val;
- uint32_t length;
- uint32_t reserved;
-};
-
-struct pk_str cstring_to_pk_str(char *s);
-struct pk_cstr cstring_to_pk_cstr(const char *s);
-struct pk_str pk_cstr_to_pk_str(const struct pk_cstr *s);
-struct pk_cstr pk_str_to_pk_cstr(const struct pk_str *s);
-int pk_compare_str(const struct pk_str *lhs, const struct pk_str *rhs);
-int pk_compare_cstr(const struct pk_cstr *lhs, const struct pk_cstr *rhs);
-
-#endif /* PK_STR_H */
-
-#ifdef PK_IMPL_STR
-
-#include <string.h>
-
-struct pk_str
-cstring_to_pk_str(char *s)
-{
- return (struct pk_str) {
- .val = s,
- .length = (uint32_t)(strlen(s)),
- .reserved = 0,
- };
-}
-
-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_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_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,
- };
-}
-
-int
-pk_compare_str(const struct pk_str *lhs, const struct pk_str *rhs)
-{
- return strncmp(lhs->val, rhs->val, PK_MIN(lhs->length, rhs->length));
-}
-
-int
-pk_compare_cstr(const struct pk_cstr *lhs, const struct pk_cstr *rhs)
-{
- return strncmp(lhs->val, rhs->val, PK_MIN(lhs->length, rhs->length));
-}
-
-#endif /* PK_IMPL_STR */
-#ifndef PK_EV_H
-#define PK_EV_H
-
-#include <stdint.h>
-
-typedef uint64_t pk_ev_mgr_id_T;
-typedef uint64_t pk_ev_id_T;
-
-// note: pk_ev_init() is NOT thread-safe
-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();
-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);
-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);
-
-#endif /* PK_EV_H */
-
-#ifdef PK_IMPL_EV
-
-#include <assert.h>
-#include <stdatomic.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <threads.h>
-#include <string.h>
-
-#ifndef PK_EV_INIT_MGR_COUNT
-# define PK_EV_INIT_MGR_COUNT 1
-#endif
-
-#ifndef PK_EV_INIT_EV_COUNT
-# define PK_EV_INIT_EV_COUNT 16
-#endif
-
-#ifndef PK_EV_INIT_CB_COUNT
-# define PK_EV_INIT_CB_COUNT 8
-#endif
-
-#ifndef PK_EV_GROW_RATIO
-# define PK_EV_GROW_RATIO 1.5
-#endif
-
-struct pk_ev_cb {
- pk_ev_cb_fn *cb;
- void *user_cb_data;
-};
-
-struct pk_ev {
- struct pk_ev_cb *ev_cbs;
- void *user_ev_data;
- atomic_uint_fast8_t n_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;
-};
-
-struct pk_ev_mstr {
- atomic_uint_fast64_t flg_mgrs;
- atomic_uint_fast64_t rn_mgrs;
- struct pk_ev_mgr **mgrs;
- mtx_t *mtxs;
-};
-
-struct pk_ev_mstr pk_ev_mstr;
-
-void
-pk_ev_init()
-{
- int i;
- pk_ev_mstr.mgrs = (struct pk_ev_mgr **)malloc(sizeof(void *) * PK_EV_INIT_MGR_COUNT);
- pk_ev_mstr.mtxs = (mtx_t*)malloc(sizeof(mtx_t) * PK_EV_INIT_MGR_COUNT);
- memset(pk_ev_mstr.mgrs, 0, sizeof(void *) * PK_EV_INIT_MGR_COUNT);
- memset(pk_ev_mstr.mtxs, 0, sizeof(mtx_t) * PK_EV_INIT_MGR_COUNT);
- for (i = 0; i < PK_EV_INIT_MGR_COUNT; ++i) {
- mtx_init(&pk_ev_mstr.mtxs[i], mtx_plain);
- }
- atomic_store(&pk_ev_mstr.flg_mgrs, 0);
- atomic_store(&pk_ev_mstr.rn_mgrs, PK_EV_INIT_MGR_COUNT);
-}
-
-void
-pk_ev_teardown()
-{
- 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]);
- free(pk_ev_mstr.mgrs[i]);
- pk_ev_mstr.mgrs[i] = NULL;
- mtx_unlock(&pk_ev_mstr.mtxs[i]);
- mtx_destroy(&pk_ev_mstr.mtxs[i]);
- }
- free(pk_ev_mstr.mgrs);
- free(pk_ev_mstr.mtxs);
- pk_ev_mstr.mgrs = NULL;
- pk_ev_mstr.mtxs = NULL;
-}
-
-static struct pk_ev_mgr*
-pk_ev_inner_ev_mgr_create(uint64_t ev_count, uint64_t cb_count)
-{
- int 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);
- size_t sz_evs = sizeof(struct pk_ev) * ev_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);
- 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);
- ev->ev_cbs = (struct pk_ev_cb*)(((char *)mgr) + sizeof(struct pk_ev_mgr) + sz_evs + (sz_ev * i));
- }
-
-early_exit:
- return mgr;
-}
-
-static void
-pk_ev_inner_ev_mgr_clone(struct pk_ev_mgr *old, struct pk_ev_mgr *mgr)
-{
- int 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));
- }
-}
-
-const pk_ev_mgr_id_T
-pk_ev_create_mgr()
-{
- uint64_t i;
- pk_ev_mgr_id_T flg;
- pk_ev_mgr_id_T flg_new;
- pk_ev_mgr_id_T id;
- struct pk_ev_mgr *mgr = pk_ev_inner_ev_mgr_create(PK_EV_INIT_EV_COUNT, PK_EV_INIT_CB_COUNT);
- if (mgr == NULL) return -1;
-start:
- flg = atomic_load(&pk_ev_mstr.flg_mgrs);
- while (1) {
- flg_new = flg;
- for (i = 0; i < atomic_load(&pk_ev_mstr.rn_mgrs); ++i) {
- if ((flg & (1u << i)) == 0) break;
- }
- if (i == atomic_load(&pk_ev_mstr.rn_mgrs)) {
- goto recreate;
- }
- id = i;
- flg_new |= (1u << i);
- if (atomic_compare_exchange_strong(&pk_ev_mstr.flg_mgrs, &flg, flg_new)) break;
- thrd_yield();
- }
- pk_ev_mstr.mgrs[id]= mgr;
- return id;
-recreate:
- // TODO recreate mgr, out of space
- assert(1 == 0 && "[pkev.h] Out of mgr space.");
- exit(1);
- goto start;
-}
-
-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_register_ev(pk_ev_mgr_id_T evmgr, void *user_ev_data)
-{
- assert(evmgr < 64);
- pk_ev_id_T id;
- struct pk_ev_mgr *mgr;
- mtx_lock(&pk_ev_mstr.mtxs[evmgr]);
- if (pk_ev_mstr.mgrs[evmgr]->n_ev == pk_ev_mstr.mgrs[evmgr]->rn_ev) {
- mgr = pk_ev_inner_ev_mgr_create(pk_ev_mstr.mgrs[evmgr]->rn_ev * PK_EV_GROW_RATIO, pk_ev_mstr.mgrs[evmgr]->rn_cb);
- pk_ev_inner_ev_mgr_clone(pk_ev_mstr.mgrs[evmgr], mgr);
- free(pk_ev_mstr.mgrs[evmgr]);
- pk_ev_mstr.mgrs[evmgr] = mgr;
- }
- id = pk_ev_mstr.mgrs[evmgr]->n_ev++;
- pk_ev_mstr.mgrs[evmgr]->ev[id].user_ev_data = user_ev_data;
- mtx_unlock(&pk_ev_mstr.mtxs[evmgr]);
- return id;
-}
-
-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)
-{
- assert(evmgr < 64);
- struct pk_ev_mgr *mgr;
- uint8_t cb_index;
- 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) {
- mgr = pk_ev_inner_ev_mgr_create(pk_ev_mstr.mgrs[evmgr]->rn_ev, pk_ev_mstr.mgrs[evmgr]->rn_cb * PK_EV_GROW_RATIO);
- 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;
-}
-
-void
-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) {
- (*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,
- user_emit_data);
- }
-}
-
-#endif /* PK_IMPL_EV */
-#endif /* PK_SINGLE_HEADER_FILE_H */