diff --git a/src/common/runtime.cpp b/src/common/runtime.cpp index 1c239f68b..3a6fffd49 100644 --- a/src/common/runtime.cpp +++ b/src/common/runtime.cpp @@ -31,10 +31,13 @@ // SDL #include +#include namespace love { static SDL_mutex *gcmutex = 0; + void *_gcmutex = 0; + unsigned int _gcthread = 0; /** * Called when an object is collected. The object is released * once in this function, possibly deleting it. @@ -42,13 +45,19 @@ namespace love static int w__gc(lua_State * L) { if (!gcmutex) + { gcmutex = SDL_CreateMutex(); + _gcmutex = (void*) gcmutex; + } Proxy * p = (Proxy *)lua_touserdata(L, 1); Object * t = (Object *)p->data; - SDL_mutexP(gcmutex); if(p->own) + { + SDL_mutexP(gcmutex); + _gcthread = (unsigned int) SDL_ThreadID(); t->release(); - SDL_mutexV(gcmutex); + SDL_mutexV(gcmutex); + } return 0; } @@ -274,7 +283,7 @@ namespace love lua_replace(L, idx); // Replace the initial argument with the new object. return 0; } - + int luax_convobj(lua_State * L, int idxs[], int n, const char * mod, const char * fn) { luax_getfunction(L, mod, fn); diff --git a/src/common/runtime.h b/src/common/runtime.h index 4d2cdd2c8..9c07d1086 100644 --- a/src/common/runtime.h +++ b/src/common/runtime.h @@ -37,6 +37,10 @@ namespace love class Module; class Reference; + // Exposed mutex of the GC + extern void *_gcmutex; + extern unsigned int _gcthread; + /** * Registries represent special tables which can be accessed with * luax_getregistry. @@ -219,14 +223,14 @@ namespace love * @param function The function in the module. **/ int luax_convobj(lua_State * L, int idx, const char * module, const char * function); - + /** * Converts an object into another object by the specified function love.module.function. - * The conversion function must accept a single object of the relevant type as its first parameter, + * The conversion function must accept a single object of the relevant type as its first parameter, * and return one value. If the function does not exist (see luax_getfunction), an error is returned. - * + * * Note that the initial object at idx is replaced by the new object. - * + * * @param L The Lua state. * @param idxs An array of indices on the stack. * @param n How many arguments are being passed. diff --git a/src/modules/thread/sdl/Thread.cpp b/src/modules/thread/sdl/Thread.cpp index 22efdd98f..0ed826f8c 100644 --- a/src/modules/thread/sdl/Thread.cpp +++ b/src/modules/thread/sdl/Thread.cpp @@ -194,7 +194,15 @@ namespace sdl delete[] data; delete comm; if (handle) + { + bool inGC = (_gcthread == SDL_GetThreadID(handle)); + bool collectSelf = (inGC && _gcthread == SDL_ThreadID()); + inGC = inGC && !collectSelf; + if (inGC) SDL_mutexP((SDL_mutex *) _gcmutex); + if (collectSelf) SDL_mutexV((SDL_mutex *) _gcmutex); SDL_KillThread(handle); + if (inGC) SDL_mutexV((SDL_mutex *) _gcmutex); + } module->unregister(name); SDL_DestroyMutex(mutex); SDL_DestroyCond(cond); @@ -211,8 +219,10 @@ namespace sdl { if (handle) { + SDL_mutexP((SDL_mutex *) _gcmutex); SDL_KillThread(handle); handle = 0; + SDL_mutexV((SDL_mutex *) _gcmutex); } }