From 3dc4e3cdcab6664b600d82aa55db64f89ca48fd8 Mon Sep 17 00:00:00 2001 From: Bart van Strien Date: Thu, 5 Jul 2012 17:25:41 +0200 Subject: [PATCH] Also mutex lock in Channel::retain --HG-- branch : minor --- src/modules/thread/Channel.cpp | 247 +++++++++++++++++---------------- src/modules/thread/Channel.h | 43 +++--- 2 files changed, 151 insertions(+), 139 deletions(-) diff --git a/src/modules/thread/Channel.cpp b/src/modules/thread/Channel.cpp index 7d9f2137a..4998f4392 100644 --- a/src/modules/thread/Channel.cpp +++ b/src/modules/thread/Channel.cpp @@ -26,136 +26,147 @@ namespace love { namespace thread { - static std::map namedChannels; - static Mutex *namedChannelMutex; - Channel *Channel::getChannel(const std::string &name) +static std::map namedChannels; +static Mutex *namedChannelMutex; +Channel *Channel::getChannel(const std::string &name) +{ + if (!namedChannelMutex) + namedChannelMutex = newMutex(); + Lock l(namedChannelMutex); + if (!namedChannels.count(name)) + namedChannels[name] = new Channel(name); + else + namedChannels[name]->retain(); + return namedChannels[name]; +} + +Channel::Channel() + : named(false) +{ + mutex = newMutex(); + cond = newConditional(); +} + +Channel::Channel(const std::string &name) + : named(true), name(name) +{ + mutex = newMutex(); + cond = newConditional(); +} + +Channel::~Channel() +{ + while (!queue.empty()) { - if (!namedChannelMutex) - namedChannelMutex = newMutex(); - Lock l(namedChannelMutex); - if (!namedChannels.count(name)) - namedChannels[name] = new Channel(name); - else - namedChannels[name]->retain(); - return namedChannels[name]; - } - - Channel::Channel() - : named(false) - { - mutex = newMutex(); - cond = newConditional(); - } - - Channel::Channel(const std::string &name) - : named(true), name(name) - { - mutex = newMutex(); - cond = newConditional(); - } - - Channel::~Channel() - { - while (!queue.empty()) - { - queue.front()->release(); - queue.pop(); - } - - delete mutex; - delete cond; - if (named) - namedChannels.erase(name); - } - - void Channel::push(Variant *var) - { - if (!var) - return; - Lock l(mutex); - var->retain(); - // Keep a reference to ourselves - // if we're non-empty and named. - if (named && queue.empty()) - retain(); - queue.push(var); - cond->signal(); - } - - Variant *Channel::pop() - { - Lock l(mutex); - if (queue.empty()) - return 0; - - Variant *var = queue.front(); + queue.front()->release(); queue.pop(); - - // Release our reference to ourselves - // if we're empty and named. - if (named && queue.empty()) - release(); - return var; - } // NOTE: Returns a retained Variant - - Variant *Channel::demand() - { - Variant *var; - while (!(var = pop())) - { - mutex->lock(); - cond->wait(mutex); - mutex->unlock(); - } - return var; } - Variant *Channel::peek() - { - Lock l(mutex); - if (queue.empty()) - return 0; + delete mutex; + delete cond; + if (named) + namedChannels.erase(name); +} - Variant *var = queue.front(); - var->retain(); - return var; +void Channel::push(Variant *var) +{ + if (!var) + return; + Lock l(mutex); + var->retain(); + // Keep a reference to ourselves + // if we're non-empty and named. + if (named && queue.empty()) + retain(); + queue.push(var); + cond->signal(); +} + +Variant *Channel::pop() +{ + Lock l(mutex); + if (queue.empty()) + return 0; + + Variant *var = queue.front(); + queue.pop(); + + // Release our reference to ourselves + // if we're empty and named. + if (named && queue.empty()) + release(); + return var; +} // NOTE: Returns a retained Variant + +Variant *Channel::demand() +{ + Variant *var; + while (!(var = pop())) + { + mutex->lock(); + cond->wait(mutex); + mutex->unlock(); + } + return var; +} + +Variant *Channel::peek() +{ + Lock l(mutex); + if (queue.empty()) + return 0; + + Variant *var = queue.front(); + var->retain(); + return var; +} + +int Channel::count() +{ + Lock l(mutex); + return queue.size(); +} + +void Channel::clear() +{ + Lock l(mutex); + + // We're already empty. + if (queue.empty()) + return; + + while (!queue.empty()) + { + queue.front()->release(); + queue.pop(); } - int Channel::count() - { - Lock l(mutex); - return queue.size(); - } + // Once again, release our own + // reference if we're named. + if (named) + release(); +} - void Channel::clear() - { - Lock l(mutex); +void Channel::retain() +{ + if (named) + namedChannelMutex->lock(); - // We're already empty. - if (queue.empty()) - return; + Object::retain(); - while (!queue.empty()) - { - queue.front()->release(); - queue.pop(); - } + if (named) + namedChannelMutex->unlock(); +} - // Once again, release our own - // reference if we're named. - if (named) - release(); - } +void Channel::release() +{ + if (named) + namedChannelMutex->lock(); - void Channel::release() - { - if (named) - namedChannelMutex->lock(); + Object::release(); - Object::release(); - - if (named) - namedChannelMutex->unlock(); - } + if (named) + namedChannelMutex->unlock(); +} } // thread } // love diff --git a/src/modules/thread/Channel.h b/src/modules/thread/Channel.h index 94d63c1b5..f3c58d1bd 100644 --- a/src/modules/thread/Channel.h +++ b/src/modules/thread/Channel.h @@ -33,30 +33,31 @@ namespace love { namespace thread { - class Channel : public love::Object - { - private: - Mutex *mutex; - Conditional *cond; - std::queue queue; - bool named; - std::string name; - Channel(const std::string &name); +class Channel : public love::Object +{ +private: + Mutex *mutex; + Conditional *cond; + std::queue queue; + bool named; + std::string name; + Channel(const std::string &name); - public: - Channel(); - ~Channel(); - static Channel *getChannel(const std::string &name); +public: + Channel(); + ~Channel(); + static Channel *getChannel(const std::string &name); - void push(Variant *var); - Variant *pop(); - Variant *demand(); - Variant *peek(); - int count(); - void clear(); + void push(Variant *var); + Variant *pop(); + Variant *demand(); + Variant *peek(); + int count(); + void clear(); - void release(); - }; // Channel + void retain(); + void release(); +}; // Channel } // thread } // love