Browse Source

Add optional timeout values to Channel:supply and Channel:demand (resolves #1344)

--HG--
branch : minor
Bart van Strien 8 years ago
parent
commit
09c1259857

+ 47 - 2
src/modules/thread/Channel.cpp

@@ -22,6 +22,8 @@
 #include <map>
 #include <map>
 #include <string>
 #include <string>
 
 
+#include <timer/Timer.h>
+
 namespace love
 namespace love
 {
 {
 namespace thread
 namespace thread
@@ -88,13 +90,35 @@ uint64 Channel::push(const Variant &var)
 	return ++sent;
 	return ++sent;
 }
 }
 
 
-void Channel::supply(const Variant &var)
+bool Channel::supply(const Variant &var)
 {
 {
 	Lock l(mutex);
 	Lock l(mutex);
 	uint64 id = push(var);
 	uint64 id = push(var);
 
 
 	while (received < id)
 	while (received < id)
 		cond->wait(mutex);
 		cond->wait(mutex);
+
+	return true;
+}
+
+bool Channel::supply(const Variant &var, double timeout)
+{
+	Lock l(mutex);
+	uint64 id = push(var);
+
+	while (timeout >= 0)
+	{
+		if (received >= id)
+			return true;
+
+		double start = love::timer::Timer::getTime();
+		cond->wait(mutex, timeout*1000);
+		double stop = love::timer::Timer::getTime();
+
+		timeout -= (stop-start);
+	}
+
+	return false;
 }
 }
 
 
 bool Channel::pop(Variant *var)
 bool Channel::pop(Variant *var)
@@ -118,12 +142,33 @@ bool Channel::pop(Variant *var)
 	return true;
 	return true;
 }
 }
 
 
-void Channel::demand(Variant *var)
+bool Channel::demand(Variant *var)
 {
 {
 	Lock l(mutex);
 	Lock l(mutex);
 
 
 	while (!pop(var))
 	while (!pop(var))
 		cond->wait(mutex);
 		cond->wait(mutex);
+
+	return true;
+}
+
+bool Channel::demand(Variant *var, double timeout)
+{
+	Lock l(mutex);
+
+	while (timeout >= 0)
+	{
+		if (pop(var))
+			return true;
+
+		double start = love::timer::Timer::getTime();
+		cond->wait(mutex, timeout*1000);
+		double stop = love::timer::Timer::getTime();
+
+		timeout -= (stop-start);
+	}
+
+	return false;
 }
 }
 
 
 bool Channel::peek(Variant *var)
 bool Channel::peek(Variant *var)

+ 4 - 2
src/modules/thread/Channel.h

@@ -50,9 +50,11 @@ public:
 	static Channel *getChannel(const std::string &name);
 	static Channel *getChannel(const std::string &name);
 
 
 	uint64 push(const Variant &var);
 	uint64 push(const Variant &var);
-	void supply(const Variant &var); // blocking push
+	bool supply(const Variant &var); // blocking push
+	bool supply(const Variant &var, double timeout);
 	bool pop(Variant *var);
 	bool pop(Variant *var);
-	void demand(Variant *var); // blocking pop
+	bool demand(Variant *var); // blocking pop
+	bool demand(Variant *var, double timeout); // blocking pop
 	bool peek(Variant *var);
 	bool peek(Variant *var);
 	int getCount() const;
 	int getCount() const;
 	bool hasRead(uint64 id) const;
 	bool hasRead(uint64 id) const;

+ 19 - 4
src/modules/thread/wrap_Channel.cpp

@@ -46,13 +46,19 @@ int w_Channel_push(lua_State *L)
 int w_Channel_supply(lua_State *L)
 int w_Channel_supply(lua_State *L)
 {
 {
 	Channel *c = luax_checkchannel(L, 1);
 	Channel *c = luax_checkchannel(L, 1);
+	bool result = false;
 	luax_catchexcept(L, [&]() {
 	luax_catchexcept(L, [&]() {
 		Variant var = Variant::fromLua(L, 2);
 		Variant var = Variant::fromLua(L, 2);
 		if (var.getType() == Variant::UNKNOWN)
 		if (var.getType() == Variant::UNKNOWN)
 			luaL_argerror(L, 2, "boolean, number, string, love type, or table expected");
 			luaL_argerror(L, 2, "boolean, number, string, love type, or table expected");
-		c->supply(var);
+		if (lua_isnumber(L, 3))
+			result = c->supply(var, lua_tonumber(L, 3));
+		else
+			result = c->supply(var);
 	});
 	});
-	return 0;
+
+	luax_pushboolean(L, result);
+	return 1;
 }
 }
 
 
 int w_Channel_pop(lua_State *L)
 int w_Channel_pop(lua_State *L)
@@ -70,8 +76,17 @@ int w_Channel_demand(lua_State *L)
 {
 {
 	Channel *c = luax_checkchannel(L, 1);
 	Channel *c = luax_checkchannel(L, 1);
 	Variant var;
 	Variant var;
-	c->demand(&var);
-	var.toLua(L);
+	bool result = false;
+
+	if (lua_isnumber(L, 2))
+		result = c->demand(&var, lua_tonumber(L, 2));
+	else
+		result = c->demand(&var);
+
+	if (result)
+		var.toLua(L);
+	else
+		lua_pushnil(L);
 	return 1;
 	return 1;
 }
 }