2017-01-20 08:36:52 -05:00
|
|
|
#pragma once
|
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
namespace Utils
|
|
|
|
{
|
|
|
|
class Memory
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
class Allocator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef void(*FreeCallback)(void*);
|
|
|
|
|
|
|
|
Allocator()
|
|
|
|
{
|
|
|
|
this->pool.clear();
|
|
|
|
this->refMemory.clear();
|
|
|
|
}
|
|
|
|
~Allocator()
|
|
|
|
{
|
|
|
|
this->clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear()
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> _(this->mutex);
|
|
|
|
|
|
|
|
for (auto i = this->refMemory.begin(); i != this->refMemory.end(); ++i)
|
|
|
|
{
|
|
|
|
if (i->first && i->second)
|
|
|
|
{
|
|
|
|
i->second(i->first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this->refMemory.clear();
|
|
|
|
|
2017-05-30 14:31:00 -04:00
|
|
|
for (auto& data : this->pool)
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
Memory::Free(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
this->pool.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void free(void* data)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> _(this->mutex);
|
|
|
|
|
|
|
|
auto i = this->refMemory.find(data);
|
|
|
|
if (i != this->refMemory.end())
|
|
|
|
{
|
|
|
|
i->second(i->first);
|
|
|
|
this->refMemory.erase(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto j = std::find(this->pool.begin(), this->pool.end(), data);
|
|
|
|
if (j != this->pool.end())
|
|
|
|
{
|
|
|
|
Memory::Free(data);
|
|
|
|
this->pool.erase(j);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void free(const void* data)
|
|
|
|
{
|
|
|
|
this->free(const_cast<void*>(data));
|
|
|
|
}
|
|
|
|
|
|
|
|
void reference(void* memory, FreeCallback callback)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> _(this->mutex);
|
|
|
|
|
|
|
|
this->refMemory[memory] = callback;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* allocate(size_t length)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> _(this->mutex);
|
|
|
|
|
|
|
|
void* data = Memory::Allocate(length);
|
|
|
|
this->pool.push_back(data);
|
|
|
|
return data;
|
|
|
|
}
|
2022-01-27 12:11:21 -05:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <typename T> inline T* allocate()
|
|
|
|
{
|
|
|
|
return this->allocateArray<T>(1);
|
|
|
|
}
|
2022-01-27 12:11:21 -05:00
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
template <typename T> inline T* allocateArray(size_t count = 1)
|
|
|
|
{
|
|
|
|
return static_cast<T*>(this->allocate(count * sizeof(T)));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool empty()
|
|
|
|
{
|
|
|
|
return (this->pool.empty() && this->refMemory.empty());
|
|
|
|
}
|
|
|
|
|
2018-12-17 08:29:18 -05:00
|
|
|
char* duplicateString(const std::string& string)
|
2017-01-19 16:23:59 -05:00
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> _(this->mutex);
|
|
|
|
|
|
|
|
char* data = Memory::DuplicateString(string);
|
|
|
|
this->pool.push_back(data);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2017-03-17 18:41:31 -04:00
|
|
|
bool isPointerMapped(void* ptr)
|
|
|
|
{
|
|
|
|
return this->ptrMap.find(ptr) != this->ptrMap.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T> T* getPointer(void* oldPtr)
|
|
|
|
{
|
|
|
|
if (this->isPointerMapped(oldPtr))
|
|
|
|
{
|
|
|
|
return reinterpret_cast<T*>(this->ptrMap[oldPtr]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mapPointer(void* oldPtr, void* newPtr)
|
|
|
|
{
|
|
|
|
this->ptrMap[oldPtr] = newPtr;
|
|
|
|
}
|
|
|
|
|
2017-01-19 16:23:59 -05:00
|
|
|
private:
|
|
|
|
std::mutex mutex;
|
2017-04-16 05:47:57 -04:00
|
|
|
std::vector<void*> pool;
|
|
|
|
std::unordered_map<void*, void*> ptrMap;
|
|
|
|
std::unordered_map<void*, FreeCallback> refMemory;
|
2017-01-19 16:23:59 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
static void* AllocateAlign(size_t length, size_t alignment);
|
|
|
|
static void* Allocate(size_t length);
|
|
|
|
template <typename T> static inline T* Allocate()
|
|
|
|
{
|
|
|
|
return AllocateArray<T>(1);
|
|
|
|
}
|
|
|
|
template <typename T> static inline T* AllocateArray(size_t count = 1)
|
|
|
|
{
|
|
|
|
return static_cast<T*>(Allocate(count * sizeof(T)));
|
|
|
|
}
|
|
|
|
|
2021-06-28 14:25:23 -04:00
|
|
|
template <typename T> static inline T* Duplicate(T* original)
|
|
|
|
{
|
|
|
|
T* data = Memory::Allocate<T>();
|
|
|
|
std::memcpy(data, original, sizeof(T));
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2018-12-17 08:29:18 -05:00
|
|
|
static char* DuplicateString(const std::string& string);
|
2017-01-19 16:23:59 -05:00
|
|
|
|
|
|
|
static void Free(void* data);
|
|
|
|
static void Free(const void* data);
|
|
|
|
|
|
|
|
static void FreeAlign(void* data);
|
|
|
|
static void FreeAlign(const void* data);
|
|
|
|
|
|
|
|
static bool IsSet(void* mem, char chr, size_t length);
|
2017-02-21 14:15:16 -05:00
|
|
|
|
|
|
|
static bool IsBadReadPtr(const void* ptr);
|
|
|
|
static bool IsBadCodePtr(const void* ptr);
|
2017-06-02 09:36:20 -04:00
|
|
|
|
|
|
|
static Utils::Memory::Allocator* GetAllocator();
|
|
|
|
|
|
|
|
private:
|
|
|
|
static Utils::Memory::Allocator MemAllocator;
|
2017-01-19 16:23:59 -05:00
|
|
|
};
|
|
|
|
}
|