From 140faf0cae845e51372ce84d04215604e47135c7 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Wed, 9 Mar 2016 22:04:14 -0400 Subject: [PATCH] Channel:push now returns an id value. Added Channel:hasRead(id), which returns true if the value that the id represents has already been popped, demanded, or cleared from the Channel. Resolves issue #1104. --HG-- branch : minor --- src/modules/thread/Channel.cpp | 40 ++++++++--------------------- src/modules/thread/Channel.h | 10 +++++--- src/modules/thread/wrap_Channel.cpp | 14 ++++++++-- 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/src/modules/thread/Channel.cpp b/src/modules/thread/Channel.cpp index 8d6180178..d1514d2d4 100644 --- a/src/modules/thread/Channel.cpp +++ b/src/modules/thread/Channel.cpp @@ -22,34 +22,11 @@ #include #include -namespace -{ -union uslong -{ - unsigned long u; - long i; -}; - -// target <= current, but semi-wrapsafe, one wrap, anyway -inline bool past(unsigned int target, unsigned int current) -{ - if (target > current) - return false; - if (target == current) - return true; - - uslong t, c; - t.u = target; - c.u = current; - - return !(t.i < 0 && c.i > 0); -} -} - namespace love { namespace thread { + static std::map namedChannels; static Mutex *namedChannelMutex; @@ -61,7 +38,6 @@ Channel *Channel::getChannel(const std::string &name) Lock lock(namedChannelMutex); auto it = namedChannels.find(name); - if (it != namedChannels.end()) { it->second->retain(); @@ -96,7 +72,7 @@ Channel::~Channel() } } -unsigned long Channel::push(const Variant &var) +uint64 Channel::push(const Variant &var) { Lock l(mutex); @@ -114,9 +90,9 @@ unsigned long Channel::push(const Variant &var) void Channel::supply(const Variant &var) { Lock l(mutex); - unsigned long id = push(var); + uint64 id = push(var); - while (!past(id, received)) + while (received < id) cond->wait(mutex); } @@ -160,12 +136,18 @@ bool Channel::peek(Variant *var) return true; } -int Channel::getCount() +int Channel::getCount() const { Lock l(mutex); return (int) queue.size(); } +bool Channel::hasRead(uint64 id) const +{ + Lock l(mutex); + return received >= id; +} + void Channel::clear() { Lock l(mutex); diff --git a/src/modules/thread/Channel.h b/src/modules/thread/Channel.h index b257415a0..5a5dafe68 100644 --- a/src/modules/thread/Channel.h +++ b/src/modules/thread/Channel.h @@ -27,6 +27,7 @@ // LOVE #include "common/Variant.h" +#include "common/int.h" #include "threads.h" namespace love @@ -46,12 +47,13 @@ public: static Channel *getChannel(const std::string &name); - unsigned long push(const Variant &var); + uint64 push(const Variant &var); void supply(const Variant &var); // blocking push bool pop(Variant *var); void demand(Variant *var); // blocking pop bool peek(Variant *var); - int getCount(); + int getCount() const; + bool hasRead(uint64 id) const; void clear(); private: @@ -66,8 +68,8 @@ private: bool named; std::string name; - unsigned long sent; - unsigned long received; + uint64 sent; + uint64 received; }; // Channel diff --git a/src/modules/thread/wrap_Channel.cpp b/src/modules/thread/wrap_Channel.cpp index ff11fb304..8fd30656f 100644 --- a/src/modules/thread/wrap_Channel.cpp +++ b/src/modules/thread/wrap_Channel.cpp @@ -36,8 +36,9 @@ int w_Channel_push(lua_State *L) Variant var; if (!Variant::fromLua(L, 2, &var)) return luaL_argerror(L, 2, "boolean, number, string, love type, or flat table expected"); - c->push(var); - return 0; + uint64 id = c->push(var); + lua_pushnumber(L, (lua_Number) id); + return 1; } int w_Channel_supply(lua_State *L) @@ -88,6 +89,14 @@ int w_Channel_getCount(lua_State *L) return 1; } +int w_Channel_hasRead(lua_State *L) +{ + Channel *c = luax_checkchannel(L, 1); + uint64 id = (uint64) luaL_checknumber(L, 2); + luax_pushboolean(L, c->hasRead(id)); + return 1; +} + int w_Channel_clear(lua_State *L) { Channel *c = luax_checkchannel(L, 1); @@ -130,6 +139,7 @@ static const luaL_Reg w_Channel_functions[] = { "demand", w_Channel_demand }, { "peek", w_Channel_peek }, { "getCount", w_Channel_getCount }, + { "hasRead", w_Channel_hasRead }, { "clear", w_Channel_clear }, { "performAtomic", w_Channel_performAtomic }, { 0, 0 }