Jelajahi Sumber

It looks like a dirty hack, it probably is, but this fixes the GC

[email protected] 15 tahun lalu
induk
melakukan
200d4bc653
3 mengubah file dengan 30 tambahan dan 7 penghapusan
  1. 12 3
      src/common/runtime.cpp
  2. 8 4
      src/common/runtime.h
  3. 10 0
      src/modules/thread/sdl/Thread.cpp

+ 12 - 3
src/common/runtime.cpp

@@ -31,10 +31,13 @@
 
 
 // SDL
 // SDL
 #include <SDL_mutex.h>
 #include <SDL_mutex.h>
+#include <SDL_thread.h>
 
 
 namespace love
 namespace love
 {
 {
 	static SDL_mutex *gcmutex = 0;
 	static SDL_mutex *gcmutex = 0;
+	void *_gcmutex = 0;
+	unsigned int _gcthread = 0;
 	/**
 	/**
 	* Called when an object is collected. The object is released
 	* Called when an object is collected. The object is released
 	* once in this function, possibly deleting it.
 	* once in this function, possibly deleting it.
@@ -42,13 +45,19 @@ namespace love
 	static int w__gc(lua_State * L)
 	static int w__gc(lua_State * L)
 	{
 	{
 		if (!gcmutex)
 		if (!gcmutex)
+		{
 			gcmutex = SDL_CreateMutex();
 			gcmutex = SDL_CreateMutex();
+			_gcmutex = (void*) gcmutex;
+		}
 		Proxy * p = (Proxy *)lua_touserdata(L, 1);
 		Proxy * p = (Proxy *)lua_touserdata(L, 1);
 		Object * t = (Object *)p->data;
 		Object * t = (Object *)p->data;
-		SDL_mutexP(gcmutex);
 		if(p->own)
 		if(p->own)
+		{
+			SDL_mutexP(gcmutex);
+			_gcthread = (unsigned int) SDL_ThreadID();
 			t->release();
 			t->release();
-		SDL_mutexV(gcmutex);
+			SDL_mutexV(gcmutex);
+		}
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -274,7 +283,7 @@ namespace love
 		lua_replace(L, idx); // Replace the initial argument with the new object.
 		lua_replace(L, idx); // Replace the initial argument with the new object.
 		return 0;
 		return 0;
 	}
 	}
-	
+
 	int luax_convobj(lua_State * L, int idxs[], int n, const char * mod, const char * fn)
 	int luax_convobj(lua_State * L, int idxs[], int n, const char * mod, const char * fn)
 	{
 	{
 		luax_getfunction(L, mod, fn);
 		luax_getfunction(L, mod, fn);

+ 8 - 4
src/common/runtime.h

@@ -37,6 +37,10 @@ namespace love
 	class Module;
 	class Module;
 	class Reference;
 	class Reference;
 
 
+	// Exposed mutex of the GC
+	extern void *_gcmutex;
+	extern unsigned int _gcthread;
+
 	/**
 	/**
 	* Registries represent special tables which can be accessed with
 	* Registries represent special tables which can be accessed with
 	* luax_getregistry.
 	* luax_getregistry.
@@ -219,14 +223,14 @@ namespace love
 	* @param function The function in the module.
 	* @param function The function in the module.
 	**/
 	**/
 	int luax_convobj(lua_State * L, int idx, const char * module, const char * function);
 	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.
 	* 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.
 	* 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.
 	* Note that the initial object at idx is replaced by the new object.
-	* 
+	*
 	* @param L The Lua state.
 	* @param L The Lua state.
 	* @param idxs An array of indices on the stack.
 	* @param idxs An array of indices on the stack.
 	* @param n How many arguments are being passed.
 	* @param n How many arguments are being passed.

+ 10 - 0
src/modules/thread/sdl/Thread.cpp

@@ -194,7 +194,15 @@ namespace sdl
 			delete[] data;
 			delete[] data;
 		delete comm;
 		delete comm;
 		if (handle)
 		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);
 			SDL_KillThread(handle);
+			if (inGC) SDL_mutexV((SDL_mutex *) _gcmutex);
+		}
 		module->unregister(name);
 		module->unregister(name);
 		SDL_DestroyMutex(mutex);
 		SDL_DestroyMutex(mutex);
 		SDL_DestroyCond(cond);
 		SDL_DestroyCond(cond);
@@ -211,8 +219,10 @@ namespace sdl
 	{
 	{
 		if (handle)
 		if (handle)
 		{
 		{
+			SDL_mutexP((SDL_mutex *) _gcmutex);
 			SDL_KillThread(handle);
 			SDL_KillThread(handle);
 			handle = 0;
 			handle = 0;
+			SDL_mutexV((SDL_mutex *) _gcmutex);
 		}
 		}
 	}
 	}