ivmai / bdwgc

The Boehm-Demers-Weiser conservative C/C++ Garbage Collector (bdwgc, also known as bdw-gc, boehm-gc, libgc)
https://www.hboehm.info/gc/
Other
2.98k stars 407 forks source link

Thread local data and roots #191

Closed intrigus closed 6 years ago

intrigus commented 6 years ago

Hello, my code looks like this:

static __thread Env env;

struct Env {
    nongcmember nogc;
    gcmember gc;    
};

struct gcmember {
    void* operator new(std::size_t sz) {
        return GC_MALLOC(sz);
    }
};

void main(){
env.gc = new gcmember();
// doo stuff
// after some time env.gc seems to get collected 
// and another object gets allocated at the position 
}

I'm initializing the Env struct in my main method. After some time I allocate the gcmember and store it in env.gc. Then my application runs for quite some time and env.gc seems to get collected.

Now I have found one solution:

GC_add_roots(&env, &env + 1);

this works well, but I'd like to remove this root after the thread exited and the thread local variables are cleaned up. So I looked at GC_CALL GC_remove_roots but in the docs it says: "May be unimplemented on some platforms." https://github.com/ivmai/bdwgc/blob/59372942a7cbb3e5ffe233823906ef8611fce716/include/gc.h#L601

Is there an easier way to use thread locals as roots?

ivmai commented 6 years ago

Thread-local objects are not scanned. Add env thread-local values to a global collection (e.g. hashtable or double-linked list). Like:

static __thread Env env; static Env *envList; // points to the first env object (of the double-linked list) or nullptr

struct Env { nongcmember nogc; gcmember gc; Env prev; // points to previous and next env objects Env next; };

PS. It's better to ask such questions on Stackoverflow - https://stackoverflow.com/questions/tagged/boehm-gc

ivmai commented 6 years ago

Or, a better way, I think, is to use GC_MALLOC_UNCOLLECTABLE:

struct Env { nongcmember nogc; gcmember gc; }; static __thread Env *penv; ... // init thread-local env: penv = GC_NEW_UNCOLLECTABLE(Env); ... // delete thread-local env: GC_FREE(penv);