📄 memmgr.cpp
字号:
#include "compiler.h"
#include "memmgr.h"
#include <new>
size_t CtkMemoryManager::GCwatermark = 64*1024;//1024*1024;
CtkMemoryManager CtkMemoryManager::instance;
CtkMemoryManager::CtkMemoryManager() {
reservedSpace = new char[64*1024];
gcActive = 0;
allocated = 0;
}
void CtkMemoryManager::notEnoughMemory()
{
delete[] reservedSpace;
reservedSpace = NULL;
ctkThrowException("Not enough memory");
}
void CtkMemoryManager::markObject(CtkObject obj) {
if (IS_OBJECT(obj) && !IS_BLACK(obj.u.ptr)) {
SET_BLACK(obj.u.ptr);
switch (obj.type) {
case CTK_STRING:
case CTK_MUTEX:
break;
case CTK_ARRAY:
{
CtkArray* arr = (CtkArray*)obj.u.ptr;
for (int i = arr->nAllocated; --i >= 0;) {
for (CtkHashEntry* e = arr->entries[i]; e != NULL; e = e->next) {
markObject(e->key);
markObject(e->value);
}
}
break;
}
case CTK_THREAD:
{
CtkThread* thread = (CtkThread*)obj.u.ptr;
CtkFrame* frm;
for (CtkQueueItem* item = thread->queue.firstItem; item != NULL; item = item->next)
{
markObject(item->value);
}
for (int i = thread->sp; --i >= 0;) {
markObject(thread->stack[i]);
}
if (thread->markFunc != NULL) {
thread->markFunc(thread);
}
for (frm = thread->callStack; frm != NULL; frm = frm->up) {
MAKE_FRAME(obj, frm);
markObject(obj);
}
for (frm = thread->exceptionTrace; frm != NULL; frm = frm->up) {
MAKE_FRAME(obj, frm);
markObject(obj);
}
markObject(thread->exceptionObject);
markObject(thread->usedObject);
break;
}
case CTK_FUNCTION:
{
CtkFrame* frame = ((CtkFunction*)obj.u.ptr)->exterior;
if (frame != NULL) {
MAKE_FRAME(obj, frame);
markObject(obj);
}
break;
}
case CTK_FRAME:
{
CtkFrame* frm = (CtkFrame*)obj.u.ptr;
CtkObject* vp = frm->vars;
int vn = frm->nVars;
while (--vn >= 0) {
markObject(*vp++);
}
if (frm->func != NULL) {
MAKE_FUNCTION(obj, frm->func);
markObject(obj);
}
break;
}
}
}
}
void* CtkMemoryManager::allocate(size_t size, CtkFinalizer finalizer) {
CtkThread* thr = ctkGetCurrentThread();
size += sizeof(CtkAllocHeader);
allocated += size;
if (allocated >= GCwatermark && thr->memoryAccess == 0) {
doGC();
}
CtkAllocHeader* hdr = (CtkAllocHeader*)malloc(size);
if (hdr == NULL) {
notEnoughMemory();
}
beginAccess(thr);
hdr->next = thr->mallocList;
hdr->finalizer = finalizer;
thr->mallocList = hdr;
if (thr->lastHeader == NULL) {
thr->lastHeader = &hdr->next;
}
endAccess(thr);
return hdr + 1;
}
void CtkMemoryManager::doGC()
{
CtkThread* thr;
CtkObject obj;
critical_section csGC(mutex);
critical_section csPool(CtkThreadPool::instance.mutex);
if (gcActive) {
return;
}
gcActive = 1;
bool existsActiveWriters;
do {
existsActiveWriters = false;
for (thr = CtkThreadPool::instance.chain; thr != NULL; thr = thr->next) {
if (thr->memoryAccess) {
#ifdef NON_BLOCKING_GARBAGE_COLLECTOR
gcActive = 0;
return;
#else
existsActiveWriters = true;
event.wait(CtkThreadPool::instance.mutex);
break;
#endif
}
}
} while (existsActiveWriters);
//
// all writers are blocked now
//
//
// Mark
//
for (thr = CtkThreadPool::instance.chain; thr != NULL; thr = thr->next) {
MAKE_THREAD(obj, thr);
markObject(obj);
}
for (CtkModule* mod = CtkCompiler::instance.modules; mod != NULL; mod = mod->next) {
MAKE_FRAME(obj, mod->frame);
markObject(obj);
}
//
// And sweep
//
thr = CtkThreadPool::instance.chain;
CtkAllocHeader *hp, **hpp = &CtkThreadPool::instance.mallocList, ***last = &CtkThreadPool::instance.lastHeader;
while (true) {
while ((hp = *hpp) != NULL) {
if ((long)hp->next & GC_BLACK) {
*(char**)&hp->next -= GC_BLACK;
hpp = &hp->next;
} else {
*hpp = hp->next;
if (hp->finalizer != NULL) {
(*hp->finalizer)(hp+1);
}
free(hp);
}
}
*last = hpp;
if (thr == NULL) {
break;
}
hpp = &thr->mallocList;
last = &thr->lastHeader;
thr = thr->next;
}
SET_WHITE(CtkThreadPool::instance.mainThread);
allocated = 0;
gcActive = 0;
// printf("GC finished\n");
}
CtkMemoryManager::~CtkMemoryManager()
{
delete[] reservedSpace;
reservedSpace = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -