1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/dennis-kk-service-box

Клонировать/Скачать
memory_allocator.hh 7.4 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
dennis-kk Отправлено 08.12.2020 11:49 5dec843
#pragma once
#include <cstdint>
#include <functional>
#include <list>
#include <memory>
#include <ostream>
#include <stdexcept>
#include <type_traits>
#include <typeinfo>
namespace kratos {
namespace service {
/**
* 内存分配器.
*
* 保证在玩家组件内分配的内存在组件卸载时都会被释放
*/
class MemoryAllocator {
private:
/**
* std::shared_ptr自定义数组删除器,只支持trival和standard_layout对象.
*
* \param p 需要销毁的数组地址
*/
template <typename T> void ptr_raw_deleter(T *p) {
if (!p) {
return;
}
dealloc(p);
}
/**
* std::shared_ptr对象删除器
*
* \param obj
*/
template <typename T> void ptr_deleter(T *obj) {
if (!obj) {
return;
}
obj->~T();
dealloc(obj);
}
/**
* std::unique_ptr对象删除器
*/
template <typename T> class UniquePtrDeleter {
MemoryAllocator *allocator_{nullptr}; ///< 内存分配器
public:
UniquePtrDeleter(MemoryAllocator *allocator) : allocator_(allocator) {}
void operator()(T *obj) {
if (!obj) {
return;
}
obj->~T();
allocator_->dealloc(obj);
}
};
/**
* std::unique_ptr数组删除器,只支持trival和standard_layout对象.
*/
template <typename T> class UniqueRawDeleter {
MemoryAllocator *allocator_{nullptr}; ///< 内存分配器
public:
UniqueRawDeleter(MemoryAllocator *allocator) : allocator_(allocator) {}
void operator()(T *p) { allocator_->dealloc(p); }
};
public:
template <typename T>
using unique_memory_ptr = std::unique_ptr<T, UniquePtrDeleter<T>>;
template <typename T>
using unique_memory_raw_ptr = std::unique_ptr<T[], UniqueRawDeleter<T>>;
public:
virtual ~MemoryAllocator() {}
/**
* 输出分配器调试信息.
*
* \param os
* \return
*/
virtual auto dump(std::ostream &os) -> void = 0;
/**
* 做一次内存快照.
*
* \return
*/
virtual auto snapshot() -> void = 0;
/**
* 分配对象
*
* \param args 构造参数
* \return 对象的共享指针
*/
template <typename T, typename... ArgsT>
auto make_shared(ArgsT... args) -> std::shared_ptr<T> {
auto pointer = alloc(sizeof(T));
return std::shared_ptr<T>(new (pointer) T(std::forward<ArgsT>(args)...),
std::bind(&MemoryAllocator::ptr_deleter<T>, this,
std::placeholders::_1));
}
/**
* 分配对象
*
* \param args 构造参数
* \param file_name 文件名
* \param line 行号
* \return 对象的共享指针
*/
template <typename T, typename... ArgsT>
auto make_shared_debug(const char* file_name, int line, ArgsT... args)
-> std::shared_ptr<T> {
auto pointer = alloc(sizeof(T), typeid(T).hash_code(), typeid(T).name(),
file_name, line);
return std::shared_ptr<T>(new (pointer) T(std::forward<ArgsT>(args)...),
std::bind(&MemoryAllocator::ptr_deleter<T>, this,
std::placeholders::_1));
}
/**
* 分配数组,只能分配trival和standard_layout类型.
*
* \param count 数组元素数量
* \return 数组共享指针
*/
template <typename T>
auto make_shared_array(std::size_t count) -> std::shared_ptr<T[]> {
if (!std::is_standard_layout<T>::value && !std::is_trivial<T>::value) {
return std::shared_ptr<T[]>();
}
return std::shared_ptr<T[]>(reinterpret_cast<T *>(alloc(count * sizeof(T))),
std::bind(&MemoryAllocator::ptr_raw_deleter<T>,
this, std::placeholders::_1));
}
/**
* 分配数组,只能分配trival和standard_layout类型.
*
* \param count 数组元素数量
* \param file_name 文件名
* \param line 行号
* \return 数组共享指针
*/
template <typename T>
auto make_shared_array_debug(std::size_t count, const char *file_name = __FILE__,
int line = __LINE__) -> std::shared_ptr<T[]> {
if (!std::is_standard_layout<T>::value && !std::is_trivial<T>::value) {
return std::shared_ptr<T[]>();
}
return std::shared_ptr<T[]>(
reinterpret_cast<T *>(alloc(count * sizeof(T), typeid(T).hash_code(),
typeid(T).name(), file_name, line)),
std::bind(&MemoryAllocator::ptr_raw_deleter<T>, this,
std::placeholders::_1));
}
/**
* 分配对象
*
* \param args 构造参数
* \return 对象的唯一指针
*/
template <typename T, typename... ArgsT>
auto make_unique(ArgsT... args) -> unique_memory_ptr<T> {
auto pointer = alloc(sizeof(T));
auto *ptr = new (pointer) T(std::forward<ArgsT>(args)...);
return unique_memory_ptr<T>(ptr, this);
}
/**
* 分配对象
*
* \param args 构造参数
* \param file_name 文件名
* \param line 行号
* \return 对象的唯一指针
*/
template <typename T, typename... ArgsT>
auto make_unique_debug(const char* file_name, int line, ArgsT... args)
-> unique_memory_ptr<T> {
auto pointer = alloc(sizeof(T), typeid(T).hash_code(), typeid(T).name(),
file_name, line);
auto *ptr = new (pointer) T(std::forward<ArgsT>(args)...);
return unique_memory_ptr<T>(ptr, this);
}
/**
* 分配数组,只能分配trival和standard_layout类型.
*
* \param count 数组元素数量
* \return 数组唯一指针
*/
template <typename T>
auto make_unique_array(std::size_t count) -> unique_memory_raw_ptr<T> {
if (!std::is_standard_layout<T>::value && !std::is_trivial<T>::value) {
return unique_memory_raw_ptr<T>(nullptr, nullptr);
}
auto ptr = reinterpret_cast<T *>(alloc(count * sizeof(T)));
return unique_memory_raw_ptr<T>(ptr, this);
}
/**
* 分配数组,只能分配trival和standard_layout类型.
*
* \param count 数组元素数量
* \param file_name 文件名
* \param line 行号
* \return 数组唯一指针
*/
template <typename T>
auto make_unique_array_debug(std::size_t count, const char *file_name = __FILE__,
int line = __LINE__) -> unique_memory_raw_ptr<T> {
if (!std::is_standard_layout<T>::value && !std::is_trivial<T>::value) {
return unique_memory_raw_ptr<T>(nullptr, nullptr);
}
auto ptr =
reinterpret_cast<T *>(alloc(count * sizeof(T), typeid(T).hash_code(),
typeid(T).name(), file_name, line));
return unique_memory_raw_ptr<T>(ptr, this);
}
private:
/**
* 容器提供的内存分配方法.
*
* \param size 需要分配的长度,字节
* \return 已分配的内存起始地址
*/
virtual auto alloc(std::size_t size) -> void * = 0;
/**
* 容器提供的内存释放方法.
*
* \param ptr 需要释放内存的起始地址,由alloc分配
* \return
*/
virtual auto dealloc(void *ptr) -> void = 0;
/**
* 容器提供的内存分配方法,调试版本
*
* \param size 需要分配的长度,字节
* \param hash_id 名字对应的hash_id
* \param name 类型名
* \param file_name 分配的文件名
* \param line 行号
* \return 已分配的内存起始地址
*/
virtual auto alloc(std::size_t size, std::size_t hash_id,
const std::string &name, const std::string &file_name,
int line) -> void * = 0;
};
} // namespace service
} // namespace kratos

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/dennis-kk-service-box.git
git@api.gitlife.ru:oschina-mirror/dennis-kk-service-box.git
oschina-mirror
dennis-kk-service-box
dennis-kk-service-box
v0.4.0-alpha