#ifndef PKE_MEMORY_HPP #define PKE_MEMORY_HPP #include "memory-type-defs.hpp" #include "macros.hpp" #include #include #include #include #include #include #include // 256MB #define DEFAULT_BUCKET_SIZE 1UL << 27 extern const std::size_t MINIMUM_ALIGNMENT; extern const std::size_t MAXIMUM_ALIGNMENT; void *Pke_New(std::size_t sz, std::size_t alignment); void *Pke_New(std::size_t sz, std::size_t alignment, MemBucket *bkt); void Pke_Delete(const void *ptr, std::size_t sz); void Pke_Delete(const void *ptr, std::size_t sz, MemBucket *bkt); bool Pke_InBucket(const void *ptr, const MemBucket *bkt); void Pke_DebugPrint(); MemBucket *Pke_BeginTransientBucket(int64_t sz = DEFAULT_BUCKET_SIZE); void Pke_EndTransientBucket(MemBucket *bkt); void Pke_ResetBucket(MemBucket *bkt); void Pke_MemoryFlush(); template inline T *Pke_New(MemBucket *bucket = nullptr) { void *ptr = nullptr; if (bucket) { ptr = Pke_New(sizeof(T), alignof(T), bucket); } else { ptr = Pke_New(sizeof(T), alignof(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, alignof(T), bucket)); } else { ptr = static_cast(Pke_New(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(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); } } #endif /* PKE_MEMORY_HPP */