Selaa lähdekoodia

love.thread can now share full userdata

[email protected] 15 vuotta sitten
vanhempi
commit
736f7ab1a2

+ 3 - 3
src/common/Object.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be

+ 7 - 7
src/common/Object.h

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -24,11 +24,11 @@
 namespace love
 {
 	/**
-	* Superclass for all object that should be able to  cross the Lua/C border 
+	* Superclass for all object that should be able to  cross the Lua/C border
 	* (this pertains to most objects).
 	*
-	* This class is an alternative to using smart pointers; it contains retain/release 
-	* methods, and will delete itself with the reference count hits zero. The wrapper 
+	* This class is an alternative to using smart pointers; it contains retain/release
+	* methods, and will delete itself with the reference count hits zero. The wrapper
 	* code assumes that all userdata inherits from this class.
 	**/
 	class Object
@@ -57,7 +57,7 @@ namespace love
 		int getReferenceCount() const;
 
 		/**
-		* Retains the Object, i.e. increases the 
+		* Retains the Object, i.e. increases the
 		* reference count by one.
 		**/
 		void retain();

+ 14 - 11
src/common/runtime.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -65,7 +65,7 @@ namespace love
 
 		// Create a reference only if the test succeeds.
 		if(lua_type(L, -1) == type)
-			r = new Reference(L); 
+			r = new Reference(L);
 		else // Pop the value even if it fails (but also if it succeeds).
 			lua_pop(L, 1);
 
@@ -210,12 +210,12 @@ namespace love
 
 		if(lua_isnil(L, -1))
 			return luaL_error(L, "Can't register searcher: package table does not exist.");
-		
+
 		lua_getfield(L, -1, "loaders");
-		
+
 		if(lua_isnil(L, -1))
 			return luaL_error(L, "Can't register searcher: package.loaders table does not exist.");
-		
+
 		int len = lua_objlen(L, -1);
 		lua_pushinteger(L, len+1);
 		lua_pushcfunction(L, f);
@@ -252,7 +252,7 @@ namespace love
 		if(lua_isnil(L, -1)) return luaL_error(L, "Could not find love.%s!", mod);
 		lua_getfield(L, -1, fn);
 		if(lua_isnil(L, -1)) return luaL_error(L, "Could not find love.%s.%s!", mod, fn);
-		
+
 		lua_remove(L, -2); // remove mod
 		lua_remove(L, -2); // remove fn
 		return 0;
@@ -313,7 +313,7 @@ namespace love
 	{
 		luax_insistglobal(L, "love");
 		luax_insist(L, -1, k);
-		
+
 		// The love table should be replaced with the top stack
 		// item. Only the reqested table should remain on the stack.
 		lua_replace(L, -2);
@@ -334,7 +334,7 @@ namespace love
 		}
 	}
 
-	StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[] = 
+	StringMap<Type, TYPE_MAX_ENUM>::Entry typeEntries[] =
 	{
 		{"Invalid", INVALID_ID},
 
@@ -385,7 +385,10 @@ namespace love
 		{"PulleyJoint", PHYSICS_PULLEY_JOINT_ID},
 		{"GearJoint", PHYSICS_GEAR_JOINT_ID},
 
-		// The modules themselves. Only add abstracted modules here. 
+		// Thread
+		{"Thread", THREAD_THREAD_ID},
+
+		// The modules themselves. Only add abstracted modules here.
 		{"filesystem", MODULE_FILESYSTEM_ID},
 		{"image", MODULE_IMAGE_ID},
 		{"sound", MODULE_SOUND_ID},

+ 13 - 11
src/modules/audio/wrap_Audio.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -54,7 +54,7 @@ namespace audio
 		}
 		else
 			return luaL_error(L, "No matching overload");
-			
+
 		return 0;
 	}
 
@@ -88,7 +88,7 @@ namespace audio
 		else
 		{
 			Source * s = luax_checksource(L, 1);
-			s->pause();			
+			s->pause();
 		}
 
 		return 0;
@@ -103,7 +103,7 @@ namespace audio
 		else
 		{
 			Source * s = luax_checksource(L, 1);
-			s->resume();		
+			s->resume();
 		}
 		return 0;
 	}
@@ -117,7 +117,7 @@ namespace audio
 		else
 		{
 			Source * s = luax_checksource(L, 1);
-			s->rewind();	
+			s->rewind();
 		}
 		return 0;
 	}
@@ -224,14 +224,14 @@ namespace audio
 	static const lua_CFunction types[] = {
 		luaopen_source,
 		0
-	};	
+	};
 
 	int luaopen_love_audio(lua_State * L)
 	{
 		if(instance == 0)
 		{
 			// Try OpenAL first.
-			try 
+			try
 			{
 				instance = new love::audio::openal::Audio();
 			}
@@ -239,7 +239,9 @@ namespace audio
 			{
 				std::cout << e.what() << std::endl;
 			}
-		}
+		}
+		else
+			instance->retain();
 
 		if(instance == 0)
 		{
@@ -273,4 +275,4 @@ namespace audio
 	}
 
 } // audio
-} // love
+} // love

+ 12 - 10
src/modules/event/sdl/wrap_Event.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -33,7 +33,7 @@ namespace event
 namespace sdl
 {
 	static Event * instance = 0;
-	
+
 	static bool to_message(lua_State * L, Event::Message & msg)
 	{
 		const char * str = luaL_checkstring(L, 1);
@@ -173,10 +173,10 @@ namespace sdl
 
 	// List of functions to wrap.
 	static const luaL_Reg functions[] = {
-		{ "pump", w_pump }, 
-		{ "poll", w_poll }, 
-		{ "wait", w_wait }, 
-		{ "push", w_push }, 
+		{ "pump", w_pump },
+		{ "poll", w_poll },
+		{ "wait", w_wait },
+		{ "push", w_push },
 		{ 0, 0 }
 	};
 
@@ -184,15 +184,17 @@ namespace sdl
 	{
 		if(instance == 0)
 		{
-			try 
+			try
 			{
 				instance = new Event();
-			} 
+			}
 			catch(Exception & e)
 			{
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 		WrappedModule w;
 		w.module = instance;

+ 2 - 0
src/modules/filesystem/physfs/wrap_Filesystem.cpp

@@ -280,6 +280,8 @@ namespace physfs
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 		WrappedModule w;
 		w.module = instance;

+ 7 - 5
src/modules/font/freetype/wrap_Font.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -37,7 +37,7 @@ namespace freetype
 	{
 		Data * d = luax_checkdata(L, 1);
 		int size = luaL_checkint(L, 2);
-		
+
 		Rasterizer * t = instance->newRasterizer(d, size);
 		luax_newtype(L, "Rasterizer", FONT_RASTERIZER_T, t);
 		return 1;
@@ -47,7 +47,7 @@ namespace freetype
 	{
 		Rasterizer * r = luax_checkrasterizer(L, 1);
 		unsigned short g = (unsigned short)luaL_checkint(L, 2);
-		
+
 		GlyphData * t = instance->newGlyphData(r, g);
 		luax_newtype(L, "GlyphData", FONT_GLYPH_DATA_T, t);
 		return 1;
@@ -79,6 +79,8 @@ namespace freetype
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 		WrappedModule w;
 		w.module = instance;

+ 24 - 22
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -118,7 +118,7 @@ namespace opengl
 			instance->setScissor();
 			return 0;
 		}
-	
+
 		int x = luaL_checkint(L, 1);
 		int y = luaL_checkint(L, 2);
 		int w = luaL_checkint(L, 3);
@@ -152,7 +152,7 @@ namespace opengl
 		} catch (love::Exception & e) {
 			luaL_error(L, e.what());
 		}
-			
+
 		if(image == 0)
 			return luaL_error(L, "Could not load image.");
 
@@ -170,13 +170,13 @@ namespace opengl
 		// Create the image.
 		Glyph * t = new Glyph(data);
 		t->load();
-			
+
 		// Push the type.
 		luax_newtype(L, "Glyph", GRAPHICS_GLYPH_T, (void*)t);
 
 		return 1;
 	}
-	
+
 	int w_newQuad(lua_State * L)
 	{
 		int x = luaL_checkint(L, 1);
@@ -190,7 +190,7 @@ namespace opengl
 
 		if (frame == 0)
 			return luaL_error(L, "Could not create frame.");
-		
+
 		luax_newtype(L, "Quad", GRAPHICS_QUAD_T, (void*)frame);
 		return 1;
 	}
@@ -232,9 +232,9 @@ namespace opengl
 
 		if(font == 0)
 			return luaL_error(L, "Could not load the font");
-		
+
 		luax_newtype(L, "Font", GRAPHICS_FONT_T, (void*)font);
-		
+
 		return 1;
 	}
 
@@ -259,7 +259,7 @@ namespace opengl
 			return luaL_error(L, "Could not load the font");
 
 		luax_newtype(L, "Font", GRAPHICS_FONT_T, (void*)font);
-		
+
 		return 1;
 	}
 
@@ -529,7 +529,7 @@ namespace opengl
 		lua_pushnumber(L, instance->getMaxPointSize());
 		return 1;
 	}
-	
+
 	int w_newScreenshot(lua_State * L)
 	{
 		love::image::Image * image = luax_getmodule<love::image::Image>(L, "image", MODULE_IMAGE_T);
@@ -539,7 +539,7 @@ namespace opengl
 	}
 
 	/**
-	* Draws an Image at the specified coordinates, with rotation and 
+	* Draws an Image at the specified coordinates, with rotation and
 	* scaling along both axes.
 	* @param x The x-coordinate.
 	* @param y The y-coordinate.
@@ -564,9 +564,9 @@ namespace opengl
 	}
 
 	/**
-	* Draws an Quad of an Image at the specified coordinates, 
+	* Draws an Quad of an Image at the specified coordinates,
 	* with rotation and scaling along both axes.
-	* 
+	*
 	* @param q The Quad to draw.
 	* @param x The x-coordinate.
 	* @param y The y-coordinate.
@@ -869,28 +869,30 @@ namespace opengl
 
 	// Types for this module.
 	static const lua_CFunction types[] = {
-		luaopen_font, 
-		luaopen_image, 
+		luaopen_font,
+		luaopen_image,
 		luaopen_glyph,
-		luaopen_frame, 
+		luaopen_frame,
 		luaopen_spritebatch,
 		luaopen_particlesystem,
-		0		
+		0
 	};
 
 	int luaopen_love_graphics(lua_State * L)
 	{
 		if(instance == 0)
 		{
-			try 
+			try
 			{
 				instance = new Graphics();
-			} 
+			}
 			catch(Exception & e)
 			{
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 		WrappedModule w;
 		w.module = instance;
@@ -909,4 +911,4 @@ namespace opengl
 
 } // opengl
 } // graphics
-} // love
+} // love

+ 9 - 7
src/modules/image/wrap_Image.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -31,7 +31,7 @@ namespace love
 namespace image
 {
 	static Image * instance = 0;
-	
+
 	int w_newImageData(lua_State * L)
 	{
 
@@ -76,7 +76,7 @@ namespace image
 		luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void*)t);
 		return 1;
 	}
-	
+
 	int w_newEncodedImageData(lua_State * L) {
 		ImageData * t = luax_checkimagedata(L, 1);
 		EncodedImageData::Format format;
@@ -102,15 +102,17 @@ namespace image
 	{
 		if(instance == 0)
 		{
-			try 
+			try
 			{
 				instance = new love::image::devil::Image();
-			} 
+			}
 			catch(Exception & e)
 			{
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 		WrappedModule w;
 		w.module = instance;

+ 8 - 6
src/modules/joystick/sdl/wrap_Joystick.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -40,7 +40,7 @@ namespace sdl
 		lua_pushstring(L, instance->getName(index));
 		return 1;
 	}
-	
+
 	int w_open(lua_State * L)
 	{
 		int index = luaL_checkint(L, 1);
@@ -155,15 +155,17 @@ namespace sdl
 	{
 		if(instance == 0)
 		{
-			try 
+			try
 			{
 				instance = new Joystick();
-			} 
+			}
 			catch(Exception & e)
 			{
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 
 		WrappedModule w;

+ 7 - 5
src/modules/keyboard/sdl/wrap_Keyboard.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -76,15 +76,17 @@ namespace sdl
 	{
 		if(instance == 0)
 		{
-			try 
+			try
 			{
 				instance = new Keyboard();
-			} 
+			}
 			catch(Exception & e)
 			{
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 		WrappedModule w;
 		w.module = instance;

+ 8 - 6
src/modules/mouse/sdl/wrap_Mouse.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -94,7 +94,7 @@ namespace sdl
 		luax_pushboolean(L, instance->isGrabbed());
 		return 1;
 	}
-	
+
 	// List of functions to wrap.
 	static const luaL_Reg functions[] = {
 		{ "getX", w_getX },
@@ -113,15 +113,17 @@ namespace sdl
 	{
 		if(instance == 0)
 		{
-			try 
+			try
 			{
 				instance = new Mouse();
-			} 
+			}
 			catch(Exception & e)
 			{
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 		WrappedModule w;
 		w.module = instance;

+ 9 - 7
src/modules/physics/box2d/wrap_Physics.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -53,7 +53,7 @@ namespace box2d
 			luax_newtype(L, "World", PHYSICS_WORLD_T, (void*)w);
 			return 1;
 		}
-		else 
+		else
 			return luaL_error(L, "Incorrect number of parameters");
 	}
 
@@ -173,7 +173,7 @@ namespace box2d
 		luax_newtype(L, "PrismaticJoint", PHYSICS_PRISMATIC_JOINT_T, (void*)j);
 		return 1;
 	}
-	
+
 	int w_newPulleyJoint(lua_State * L)
 	{
 		Body * body1 = luax_checktype<Body>(L, 1, "Body", PHYSICS_BODY_T);
@@ -187,12 +187,12 @@ namespace box2d
 		float x2 = (float)luaL_checknumber(L, 9);
 		float y2 = (float)luaL_checknumber(L, 10);
 		float ratio = (float)luaL_optnumber(L, 11, 1.0);
-		
+
 		PulleyJoint * j = instance->newPulleyJoint(body1, body2, b2Vec2(gx1,gy1), b2Vec2(gx2,gy2), b2Vec2(x1,y1), b2Vec2(x2,y2), ratio);
 		luax_newtype(L, "PulleyJoint", PHYSICS_PULLEY_JOINT_T, (void*)j);
 		return 1;
 	}
-	
+
 	int w_newGearJoint(lua_State * L)
 	{
 		Joint * joint1 = luax_checktype<Joint>(L, 1, "Joint", PHYSICS_JOINT_T);
@@ -250,6 +250,8 @@ namespace box2d
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 		WrappedModule w;
 		w.module = instance;

+ 5 - 3
src/modules/sound/wrap_Sound.cpp

@@ -1,14 +1,14 @@
 /**
 * Copyright (c) 2006-2010 LOVE Development Team
-* 
+*
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
-* 
+*
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
-* 
+*
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
@@ -127,6 +127,8 @@ namespace sound
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 
 		WrappedModule w;

+ 16 - 1
src/modules/thread/sdl/Thread.cpp

@@ -79,10 +79,20 @@ namespace sdl
 
 	ThreadVariant::ThreadVariant(void *userdata)
 	{
-		type = USERDATA;
+		type = LUSERDATA;
 		data.userdata = userdata;
 	}
 
+	ThreadVariant::ThreadVariant(Type udatatype, void *userdata)
+	{
+		type = FUSERDATA;
+		this->udatatype = udatatype;
+		Proxy *p = (Proxy *) userdata;
+		flags = p->flags;
+		data.userdata = p->data;
+		((love::Object *) data.userdata)->retain();
+	}
+
 	ThreadVariant::~ThreadVariant()
 	{
 		switch(type)
@@ -90,6 +100,9 @@ namespace sdl
 			case STRING:
 				delete[] data.string;
 				break;
+			case FUSERDATA:
+				((love::Object *) data.userdata)->release();
+				break;
 		}
 	}
 
@@ -222,6 +235,8 @@ namespace sdl
 		ThreadVariant *v = comm->getValue(name);
 		while (!v)
 		{
+			if (comm->getValue("error"))
+				return 0;
 			SDL_CondWait(cond, mutex);
 			v = comm->getValue(name);
 		}

+ 5 - 1
src/modules/thread/sdl/Thread.h

@@ -52,7 +52,8 @@ namespace sdl
 		BOOLEAN,
 		NUMBER,
 		STRING,
-		USERDATA
+		LUSERDATA,
+		FUSERDATA
 	};
 
 	class ThreadVariant : public love::Object
@@ -62,6 +63,7 @@ namespace sdl
 		ThreadVariant(double number);
 		ThreadVariant(const char *string);
 		ThreadVariant(void *userdata);
+		ThreadVariant(Type udatatype, void *userdata);
 		~ThreadVariant();
 		ThreadVariantType type;
 		union
@@ -71,6 +73,8 @@ namespace sdl
 			const char *string;
 			void *userdata;
 		} data;
+		Type udatatype;
+		bits flags;
 	};
 
 	class ThreadData

+ 41 - 3
src/modules/thread/sdl/wrap_Thread.cpp

@@ -82,9 +82,15 @@ namespace sdl
 			case STRING:
 				lua_pushstring(L, v->data.string);
 				break;
-			case USERDATA: //FIXME: full userdata
+			case LUSERDATA:
 				lua_pushlightuserdata(L, v->data.userdata);
 				break;
+			case FUSERDATA:
+				const char *name;
+				love::types.find(v->udatatype, name);
+				((love::Object *) v->data.userdata)->retain();
+				luax_newtype(L, name, v->flags, v->data.userdata);
+				break;
 			default:
 				lua_pushnil(L);
 				break;
@@ -116,9 +122,15 @@ namespace sdl
 			case STRING:
 				lua_pushstring(L, v->data.string);
 				break;
-			case USERDATA: //FIXME: full userdata
+			case LUSERDATA:
 				lua_pushlightuserdata(L, v->data.userdata);
 				break;
+			case FUSERDATA:
+				const char *name;
+				types.find(v->udatatype, name);
+				((love::Object *) v->data.userdata)->retain();
+				luax_newtype(L, name, v->flags, v->data.userdata);
+				break;
 			default:
 				lua_pushnil(L);
 				break;
@@ -149,9 +161,15 @@ namespace sdl
 			case STRING:
 				lua_pushstring(L, v->data.string);
 				break;
-			case USERDATA: //FIXME: full userdata
+			case LUSERDATA:
 				lua_pushlightuserdata(L, v->data.userdata);
 				break;
+			case FUSERDATA:
+				const char *name;
+				types.find(v->udatatype, name);
+				((love::Object *) v->data.userdata)->retain();
+				luax_newtype(L, name, v->flags, v->data.userdata);
+				break;
 			default:
 				lua_pushnil(L);
 				break;
@@ -160,6 +178,22 @@ namespace sdl
 		return 1;
 	}
 
+	Type extractudatatype(lua_State * L, int idx)
+	{
+		Type t = INVALID_ID;
+		if (!lua_isuserdata(L, idx))
+			return t;
+		if (luaL_getmetafield (L, idx, "__tostring") == 0)
+			return t;
+		lua_pushvalue(L, idx);
+		int result = lua_pcall(L, 1, 1, 0);
+		if (result == 0)
+			types.find(lua_tostring(L, -1), t);
+		if (result == 0 || result == LUA_ERRRUN)
+			lua_pop(L, 1);
+		return t;
+	}
+
 	int w_Thread_send(lua_State *L)
 	{
 		Thread *t = luax_checkthread(L, 1);
@@ -181,6 +215,10 @@ namespace sdl
 		{
 			v = new ThreadVariant(lua_touserdata(L, 3));
 		}
+		else if (lua_isuserdata(L, 3))
+		{
+			v = new ThreadVariant(extractudatatype(L, 3), lua_touserdata(L, 3));
+		}
 		else
 		{
 			return luaL_error(L, "Expected boolean, number, string or userdata");

+ 1 - 0
src/modules/thread/sdl/wrap_Thread.h

@@ -27,6 +27,7 @@
 
 namespace love
 {
+	extern StringMap<Type, TYPE_MAX_ENUM> types;
 namespace thread
 {
 namespace sdl

+ 2 - 0
src/modules/timer/sdl/wrap_Timer.cpp

@@ -91,6 +91,8 @@ namespace sdl
 				return luaL_error(L, e.what());
 			}
 		}
+		else
+			instance->retain();
 
 		WrappedModule w;
 		w.module = instance;