また、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