#ifndef PKE_MEMORY_HPP #define PKE_MEMORY_HPP #include "macros.hpp" #include #include #include #include #include #include #include // 256MB #define DEFAULT_BUCKET_SIZE 1UL << 27 struct MemBucket; template struct BucketContainer { uint64_t incrementer = 2; CT bucketCounter{0}; CT itemCounter{0}; T *buckets = nullptr; }; void *Pke_New(std::size_t sz); void *Pke_New(std::size_t sz, MemBucket *bkt); void Pke_Delete(const void *ptr, std::size_t sz); void Pke_Delete(const void *ptr, std::size_t sz, MemBucket *bkt); void Pke_DebugPrint(); MemBucket *Pke_BeginTransientBucket(int64_t sz = DEFAULT_BUCKET_SIZE); void Pke_EndTransientBucket(MemBucket *bkt); void Pke_MemoryFlush(); template inline T *Pke_New(MemBucket *bucket = nullptr) { void *ptr = nullptr; if (bucket) { ptr = Pke_New(sizeof(T), bucket); } else { ptr = Pke_New(sizeof(T)); } if IS_CONSTRUCTIBLE(T) { return new (ptr) T{}; } return reinterpret_cast(ptr); } template inline T *Pke_New(long count, MemBucket *bucket = nullptr) { char *ptr = nullptr; if (bucket) { ptr = static_cast(Pke_New(sizeof(T) * count, bucket)); } else { ptr = static_cast(Pke_New(sizeof(T) * count)); } if IS_CONSTRUCTIBLE(T) { for (long i = 0; i < count; ++i) { new (ptr + (i * sizeof(T))) T{}; } } return reinterpret_cast(ptr); } template inline void Pke_Delete(const void *ptr, MemBucket *bucket = nullptr) { if IS_DESTRUCTIBLE(T) { reinterpret_cast(ptr)->~T(); } if (bucket) { return Pke_Delete(ptr, sizeof(T), bucket); } else { return Pke_Delete(ptr, sizeof(T)); } } template inline void Pke_Delete(const void *ptr, long count, MemBucket *bucket = nullptr) { if IS_DESTRUCTIBLE(T) { for (long i = 0; i < count; ++i) { reinterpret_cast(reinterpret_cast(ptr) + (i * sizeof(T)))->~T(); } } if (bucket) { return Pke_Delete(ptr, sizeof(T) * count, bucket); } else { return Pke_Delete(ptr, sizeof(T) * count); } } template void Buckets_Init(BucketContainer &bktContainer) { assert(bktContainer.buckets == nullptr && "bucket container already initialized"); bktContainer.buckets = Pke_New(bktContainer.incrementer); } uint64_t Buckets_NewHandle(std::size_t bucketBytes, uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, void*& buckets); template inline uint64_t Buckets_NewHandle(uint64_t bucketItemCount, uint64_t &bucketIncrementer, uint64_t &bucketCounter, uint64_t &itemCounter, T*& buckets) { void *ptr = reinterpret_cast(buckets); uint64_t handle = Buckets_NewHandle(sizeof(T), bucketItemCount, bucketIncrementer, bucketCounter, itemCounter, ptr); buckets = reinterpret_cast(ptr); return handle; } template inline CT Buckets_NewHandle(uint64_t maxBucketItemCount, BucketContainer &bktContainer) { return Buckets_NewHandle(maxBucketItemCount, bktContainer.incrementer, bktContainer.bucketCounter, bktContainer.itemCounter, bktContainer.buckets); } static inline constexpr uint64_t Buckets_GetBucketIndex(uint64_t handle) { return handle & 0x00000000FFFFFFFF; } static inline constexpr uint64_t Buckets_GetItemIndex(uint64_t handle) { return handle >> 32; } template static inline constexpr void Buckets_Destroy(BucketContainer &bktContainer) { if (bktContainer.buckets == nullptr || bktContainer.buckets == CAFE_BABE(T)) return; Pke_Delete(bktContainer.buckets, bktContainer.bucketCounter); bktContainer.buckets = CAFE_BABE(T); } #endif /* PKE_MEMORY_HPP */