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 InitMyHeap() {
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 TerminateMyHeap() {
for (int i = 0; i < 3; ++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);
path_ = reinterpret_cast<char*>(path);
vertices_ = reinterpret_cast<float*>(h.Alloc(1024 * 3 * sizeof(float)));
triangles_ = reinterpret_cast<uint16_t*>(h.Alloc(512 * 3 * sizeof(uint16_t)));
return vertices_ && triangles_;
}
private:
GraphicsObject()
NLIB_NOEXCEPT : IDisposer(heap_handle[kGraphcisObjectHeap]) {
path_ = NULL;
vertices_ = NULL;
triangles_ = NULL;
}
nlib_printf(
" GraphicsObject::~GraphicsObject() begin, free its data members\n");
HeapHandle h = GetHeapHandle();
h.Free(const_cast<char*>(path_));
h.Free(vertices_);
h.Free(triangles_);
nlib_printf(
" GraphicsObject::~GraphicsObject() end\n");
}
private:
const char* path_;
float* vertices_;
uint16_t* 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);
path_ = reinterpret_cast<char*>(path);
wavedata_count_ = 2;
wavedata_ = (void**)h.Alloc(n * sizeof(*wavedata_));
if (!wavedata_) return false;
for (size_t i = 0; i < wavedata_count_; ++i) {
wavedata_[i] = NULL;
}
for (size_t i = 0; i < wavedata_count_; ++i) {
wavedata_[i] = h.Alloc(8192);
if (!wavedata_[i]) return false;
}
return true;
}
private:
SoundObject()
NLIB_NOEXCEPT : IDisposer(heap_handle[kSoundObjectHeap]) {
wavedata_count_ = 0;
wavedata_ = NULL;
}
nlib_printf(
" SoundObject::~SoundObject() begin, free its data members\n");
HeapHandle h = GetHeapHandle();
h.Free(const_cast<char*>(path_));
for (size_t i = 0; i < wavedata_count_; ++i) {
h.Free(wavedata_[i]);
}
h.Free(wavedata_);
}
private:
const char* path_;
size_t wavedata_count_;
void** 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");
data_ = GetHeapHandle().Alloc(1024);
if (!data_) return false;
return true;
}
private:
data_ = NULL;
}
nlib_printf(
" MiscObject::~MiscObject() begin, free its data members\n");
GetHeapHandle().Free(data_);
}
private:
void* 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) {
graphics_object_ = GraphicsObject::Create();
if (!graphics_object_ || !graphics_object_->Init(graphics_res_path)) return false;
sound_object_ = SoundObject::Create();
if (!sound_object_ || !sound_object_->Init(sound_res_path)) return false;
misc_object_ = MiscObject::Create(GetHeapHandle());
if (!misc_object_ || !misc_object_->Init()) return false;
return true;
}
private:
explicit CharacterObject(HeapHandle h)
NLIB_NOEXCEPT : IDisposer(h) {
graphics_object_ = NULL;
sound_object_ = NULL;
misc_object_ = NULL;
}
nlib_printf(
" CharacterObject::~CharacterObject() begin, free its data members\n");
if (graphics_object_) graphics_object_->Destroy();
if (sound_object_) sound_object_->Destroy();
if (misc_object_) misc_object_->Destroy();
nlib_printf(
" CharacterObject::~CharacterObject() end\n");
}
private:
GraphicsObject* graphics_object_;
SoundObject* sound_object_;
MiscObject* misc_object_;
};
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**) {
InitMyHeap();
bool result = TestGraphicsObject();
TerminateMyHeap();
return result;
}
NLIB_MAINFUNC