Registriert: Mo Nov 08, 2010 18:41 Beiträge: 769
Programmiersprache: Gestern
Diese Version ist sehr viel langsamer, dafür gibt es jetzt aber endlich den "worldstop". Dabei werden die Threads der registrierten Roots kurz während der Collection pausiert. Die Frage ist jetzt ob man das Suspend und Resume irgendwie umgehen könnte...
Code:
//This is free and unencumbered software released into the public domain.
//
//Anyone is free to copy, modify, publish, use, compile, sell, or
//distribute this software, either in source code form or as a compiled
//binary, for any purpose, commercial or non - commercial, and by any
//means.
//
//In jurisdictions that recognize copyright laws, the author or authors
//of this software dedicate any and all copyright interest in the
//software to the public domain.We make this dedication for the benefit
//of the public at large and to the detriment of our heirs and
//successors.We intend this dedication to be an overt act of
//relinquishment in perpetuity of all present and future rights to this
//software under copyright law.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
//MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
//OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
//ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//OTHER DEALINGS IN THE SOFTWARE.
//
//For more information, please refer to <http://unlicense.org/>
#include "shared.h"
//a simple linked list used by the garbage collector to build and
//handle searches for references. Each reference found by the GC, will
//be added to the list so we can search for children.
struct memrng_t {
char* min;
char* max;
memrng_t * gcnext;
};
struct memroot_t : memrng_t {
thread_id_t tid;
HANDLE thread;
};
//the following defines a ring-buffer for memory allocations. Each
//node contains a lock so we can use it for "none-blocking" garbage
//collection.
struct memhdr_t : memrng_t {
size_t size;//includes header and fragments
bool mark;
bool isunused;
memhdr_t * next;
memhdr_t * skipprev;
memhdr_t * skipnext;
lock_t plock;
};
static lock_t rlock = lock_t();
staticint num_roots =0;
static memroot_t * roots =NULL;
static memhdr_t * pool =NULL;
static memhdr_t * pcur =NULL;
staticchar* ps =NULL;
staticchar* pe =NULL;
static memhdr_t ** memcar =NULL;
int num_objects =0;
int num_deallocs =0;
void GCCollect(void){
if(rlock.trylock()){
DWORD cid = GetCurrentThreadId();
memhdr_t * cur = pool;
memhdr_t * prev =NULL;
memhdr_t * fnd[NUM_SCAN_BUFFER +1];
char* min[NUM_SCAN_BUFFER +1];
char* max[NUM_SCAN_BUFFER +1];
memrng_t * check =NULL;
memrng_t * fcheck =NULL;
char* ptr =NULL;
int mc =0;
int tc =0;
bool found =false;
size_t l =(pe - ps)/ NUM_SCAN_BUFFER +1;
size_t h =0;
size_t g =0;
memset(max, 0, sizeof(max));
memset(min, 0xFFFFFF, sizeof(min));
memset(fnd, 0, sizeof(min));
//walk through each node and mark used nodes
//for garbage collection. Each node will be
//locked. It becomes unlocked when the next
//is locked or when the operation is completed.
do{
cur->plock.lock();
if(prev){
prev->plock.unlock();
prev =NULL;
}
if(cur->isunused){
prev = cur;
}else{
h =((size_t)cur->min)/ l;
if(cur->min < min[h]){
min[h]= cur->min;
}
if(cur->max > max[h]){
max[h]= cur->max;
}
if(fnd[h]){
fnd[h]->skipprev = cur;
}
cur->skipnext = fnd[h];
fnd[h]= cur;
cur->mark =true;
cur->isunused =true;
++mc;
}
cur = cur->next;
}while(cur != pool);
num_objects = mc;
if(prev){
prev->plock.unlock();
prev =NULL;
}
tc = mc;
//The following searches each node of a list for
//references to previously allocated memory. Each
//list item represents a range for memory from which
//each byte is searched for references to a block of
//memory.
for(int r =0; r < num_roots; r++){
roots[r].gcnext= check;
check =&(roots[r]);
}
fcheck = check;
while(check && tc){
char* c = check->min;
char* e = check->max;
while(c < e && tc){
ptr =*((char**)c++);
if(ptr){
h =((size_t)ptr)/ l;
found =false;
for(int i = h; i <= NUM_SCAN_BUFFER &&!found; i++){
if(ptr >= min[h]&& ptr <= max[h]){
g =(ps - ps)/sizeof(memhdr_t);
cur = memcar[g];
if(cur && cur->mark && cur->isunused){
cur->isunused =false;
cur->mark =false;
--tc;
if(cur->skipprev){
cur->skipprev->skipnext = cur->skipnext;
}else{
fnd[h]= cur->skipnext;
}
cur->gcnext = check->gcnext;
check->gcnext = cur;
cur->plock.unlock();
found =true;
c +=sizeof(char*)-1;
}
}
}
}else{
c +=sizeof(char*)-1;
}
}
if(check == check->gcnext){
system("pause");
}
check = check->gcnext;
}
//run collection a second time but this time pause
//any registered thread so we can be that nothing is
//misssed
if(tc >0){
for(int r =0; r < num_roots; r++){
if(cid != roots[r].tid.tid){
//pause threads so pointers can't be moved
while(SuspendThread(roots[r].thread)==(DWORD)-1){
Sleep(20);
}
}
}
check = fcheck;
while(check && tc){
char* c = check->min;
char* e = check->max;
while(c < e && tc){
ptr =*((char**)c++);
if(ptr){
h =((size_t)ptr)/ l;
found =false;
for(int i = h; i <= NUM_SCAN_BUFFER &&!found; i++){
if(ptr >= min[h]&& ptr <= max[h]){
g =(ps - ps)/sizeof(memhdr_t);
cur = memcar[g];
if(cur && cur->mark && cur->isunused){
cur->isunused =false;
cur->mark =false;
--tc;
if(cur->skipprev){
cur->skipprev->skipnext = cur->skipnext;
}else{
fnd[h]= cur->skipnext;
}
cur->gcnext = check->gcnext;
check->gcnext = cur;
cur->plock.unlock();
found =true;
c +=sizeof(char*)-1;
}
}
}
}else{
c +=sizeof(char*)-1;
}
}
if(check == check->gcnext){
system("pause");
}
check = check->gcnext;
}
for(int r =0; r < num_roots; r++){
if(cid != roots[r].tid.tid){
//resume threads
while(ResumeThread(roots[r].thread)==(DWORD)-1){
Sleep(20);
}
}
}
}
//now walk through each remaining node and unlock them
Mitglieder in diesem Forum: 0 Mitglieder und 22 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.