diff --git a/src/modules/thread/Channel.cpp b/src/modules/thread/Channel.cpp index 90384b842..97f69a34d 100644 --- a/src/modules/thread/Channel.cpp +++ b/src/modules/thread/Channel.cpp @@ -22,6 +22,8 @@ #include #include +#include + namespace love { namespace thread @@ -88,13 +90,35 @@ uint64 Channel::push(const Variant &var) return ++sent; } -void Channel::supply(const Variant &var) +bool Channel::supply(const Variant &var) { Lock l(mutex); uint64 id = push(var); while (received < id) 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) @@ -118,12 +142,33 @@ bool Channel::pop(Variant *var) return true; } -void Channel::demand(Variant *var) +bool Channel::demand(Variant *var) { Lock l(mutex); while (!pop(var)) 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) diff --git a/src/modules/thread/Channel.h b/src/modules/thread/Channel.h index f15a46a29..6dc6c851b 100644 --- a/src/modules/thread/Channel.h +++ b/src/modules/thread/Channel.h @@ -50,9 +50,11 @@ public: static Channel *getChannel(const std::string &name); 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); - void demand(Variant *var); // blocking pop + bool demand(Variant *var); // blocking pop + bool demand(Variant *var, double timeout); // blocking pop bool peek(Variant *var); int getCount() const; bool hasRead(uint64 id) const; diff --git a/src/modules/thread/wrap_Channel.cpp b/src/modules/thread/wrap_Channel.cpp index 41fb8733f..c6d157f99 100644 --- a/src/modules/thread/wrap_Channel.cpp +++ b/src/modules/thread/wrap_Channel.cpp @@ -46,13 +46,19 @@ int w_Channel_push(lua_State *L) int w_Channel_supply(lua_State *L) { Channel *c = luax_checkchannel(L, 1); + bool result = false; luax_catchexcept(L, [&]() { Variant var = Variant::fromLua(L, 2); if (var.getType() == Variant::UNKNOWN) 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) @@ -70,8 +76,17 @@ int w_Channel_demand(lua_State *L) { Channel *c = luax_checkchannel(L, 1); 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; }