⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memmgr.cpp

📁 C-Talk is interpreted scripting language with C-like syntax and dynamic type checking. Variables in
💻 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 + -