The heap systems that generally tend to be used in game programs are instantiated using nn::nlib::heap::CentralHeap
.
Separating memory and using multiple heaps has the following advantages.
Classes that allocate memory from different heaps for each object can also be created by instantiating objects from the Factory method pattern (derived from IDisposer
).
#include "gameheap.h"
using nlib_ns::heap::CentralHeap;
const int kGraphcisObjectHeap = 1;
const int kSoundObjectHeap = 2;
static char mymem[3][1024 * 1024 * 2];
static HeapHandle heap_handle[3];
void init_my_heap() {
nlib_printf(
"Graphics objects and Sound objects are allocated from different regions\n");
for (int i = 0; i < 3; ++i) {
heap_handle[i] = HeapHandle::createHeap(&mymem[i][0], 1024 * 1024 * 2);
NLIB_ASSERT(heap_handle[i].isValid());
(void*)&mymem[i][0], (void*)(&mymem[i][0] + 1024 * 1024 * 2));
}
nlib_printf(
"GraphicsObject <---- Heap%d\n", kGraphcisObjectHeap);
nlib_printf(
"SoundObject <---- Heap%d\n", kSoundObjectHeap);
}
void terminate_my_heap() {
for (int i = 0; i < 8; ++i) {
HeapHandle::destroyHeap(heap_handle[i]);
}
}
class GraphicsObject : public IDisposer {
public:
static GraphicsObject* Create() {
nlib_printf(
" GraphicsObject::Create begin, allocate GraphicsObject itself\n");
HeapHandle h = heap_handle[kGraphcisObjectHeap];
void* mem = h.alloc(
sizeof(GraphicsObject),
NLIB_ALIGNOF(GraphicsObject));
GraphicsObject* obj = new(mem)GraphicsObject();
return obj;
}
bool Init(const char* resource_path) {
nlib_printf(
" GraphicsObject::Init begin, allocate its data members\n");
NLIB_ASSERT(resource_path);
size_t n = strlen(resource_path);
HeapHandle h = GetHeapHandle();
void* path = h.alloc(n + 1);
if (!path) return false;
memcpy(path, resource_path, n + 1);
m_Path = reinterpret_cast<char*>(path);
m_Vertices = reinterpret_cast<float*>(h.alloc(1024 * 3 * sizeof(float)));
m_Triangles = reinterpret_cast<uint16_t*>(h.alloc(512 * 3 * sizeof(uint16_t)));
return m_Vertices && m_Triangles;
}
private:
GraphicsObject()
NLIB_NOEXCEPT : IDisposer(heap_handle[kGraphcisObjectHeap]) {
m_Path = NULL;
m_Vertices = NULL;
m_Triangles = NULL;
}
nlib_printf(
" GraphicsObject::~GraphicsObject() begin, free its data members\n");
HeapHandle h = GetHeapHandle();
h.free(const_cast<char*>(m_Path));
h.free(m_Vertices);
h.free(m_Triangles);
nlib_printf(
" GraphicsObject::~GraphicsObject() end\n");
}
private:
const char* m_Path;
float* m_Vertices;
uint16_t* m_Triangles;
};
class SoundObject : public IDisposer {
public:
static SoundObject* Create() {
nlib_printf(
" SoundObject::Crate() begin, allocate SoundObject itself\n");
HeapHandle h = heap_handle[kSoundObjectHeap];
void* mem = h.alloc(
sizeof(SoundObject),
NLIB_ALIGNOF(SoundObject));
SoundObject* obj = new(mem)SoundObject();
return obj;
}
bool Init(const char* resource_path) {
nlib_printf(
" SoundObject::Init() begin, allocate its data members\n");
NLIB_ASSERT(resource_path);
size_t n = strlen(resource_path);
HeapHandle h = GetHeapHandle();
void* path = h.alloc(n + 1);
if (!path) return false;
memcpy(path, resource_path, n + 1);
m_Path = reinterpret_cast<char*>(path);
m_WaveDataCnt = 2;
m_WaveData = (void**)h.alloc(n * sizeof(*m_WaveData));
if (!m_WaveData) return false;
for (size_t i = 0; i < m_WaveDataCnt; ++i) {
m_WaveData[i] = NULL;
}
for (size_t i = 0; i < m_WaveDataCnt; ++i) {
m_WaveData[i] = h.alloc(8192);
if (!m_WaveData[i]) return false;
}
return true;
}
private:
SoundObject()
NLIB_NOEXCEPT : IDisposer(heap_handle[kSoundObjectHeap]) {
m_WaveDataCnt = 0;
m_WaveData = NULL;
}
nlib_printf(
" SoundObject::~SoundObject() begin, free its data members\n");
HeapHandle h = GetHeapHandle();
h.free(const_cast<char*>(m_Path));
for (size_t i = 0; i < m_WaveDataCnt; ++i) {
h.free(m_WaveData[i]);
}
h.free(m_WaveData);
}
private:
const char* m_Path;
size_t m_WaveDataCnt;
void** m_WaveData;
};
class MiscObject : public IDisposer {
public:
static MiscObject* Create(HeapHandle h) {
nlib_printf(
" MiscObject::Create begin, allocate MiscObject itself\n");
void* mem = h.alloc(
sizeof(MiscObject),
NLIB_ALIGNOF(MiscObject));
if (!mem) return NULL;
MiscObject* obj = new(mem)MiscObject(h);
return obj;
}
bool Init() {
nlib_printf(
" MiscObject::Init begin, allocate its data members\n");
m_Data = GetHeapHandle().alloc(1024);
if (!m_Data) return false;
return true;
}
private:
m_Data = NULL;
}
nlib_printf(
" MiscObject::~MiscObject() begin, free its data members\n");
GetHeapHandle().free(m_Data);
}
private:
void* m_Data;
};
class CharacterObject : public IDisposer {
public:
static CharacterObject* Create() {
nlib_printf(
" CharacterObject::Create begin, allocate CharacterObject itself\n");
HeapHandle h = GetThreadDefaultHeapHandle();
void* mem = h.alloc(
sizeof(CharacterObject),
NLIB_ALIGNOF(CharacterObject));
CharacterObject* obj = new(mem)CharacterObject(h);
return obj;
}
bool Init(const char* graphics_res_path, const char* sound_res_path) {
m_GraphicsObject = GraphicsObject::Create();
if (!m_GraphicsObject || !m_GraphicsObject->Init(graphics_res_path)) return false;
m_SoundObject = SoundObject::Create();
if (!m_SoundObject || !m_SoundObject->Init(sound_res_path)) return false;
m_MiscObject = MiscObject::Create(GetHeapHandle());
if (!m_MiscObject || !m_MiscObject->Init()) return false;
return true;
}
private:
explicit CharacterObject(HeapHandle h)
NLIB_NOEXCEPT : IDisposer(h) {
m_GraphicsObject = NULL;
m_SoundObject = NULL;
m_MiscObject = NULL;
}
nlib_printf(
" CharacterObject::~CharacterObject() begin, free its data members\n");
if (m_GraphicsObject) m_GraphicsObject->Destroy();
if (m_SoundObject) m_SoundObject->Destroy();
if (m_MiscObject) m_MiscObject->Destroy();
nlib_printf(
" CharacterObject::~CharacterObject() end\n");
}
private:
GraphicsObject* m_GraphicsObject;
SoundObject* m_SoundObject;
MiscObject* m_MiscObject;
};
bool TestGraphicsObject() {
SetThreadDefaultHeapHandle(heap_handle[0]);
CharacterObject* cobj = CharacterObject::Create();
if (!cobj || !cobj->Init("graphics_resource.bin", "sound_resource.bin")) {
return false;
}
cobj->Destroy();
if (!heap_handle[0].isClean()) {
heap_handle[0].freeAll();
return false;
}
if (!heap_handle[1].isClean()) {
heap_handle[1].freeAll();
return false;
}
if (!heap_handle[2].isClean()) {
heap_handle[2].freeAll();
return false;
}
return true;
}
static bool SampleMain(int, char**) {
init_my_heap();
bool result = TestGraphicsObject();
terminate_my_heap();
return result;
}
NLIB_MAINFUNC