diff src/modules/thread/Channel.cpp @ 1098:a74672ba1320 minor

Merge in channels from love-experiments Rewritten love.thread and changed communication method from weird system before, to channels.
author Bart van Strien <bart.bes+projects@gmail.com>
date Wed, 04 Jul 2012 17:15:16 +0200
parents
children 025c67973ad4
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/modules/thread/Channel.cpp	Wed Jul 04 17:15:16 2012 +0200
@@ -0,0 +1,148 @@
+/**
+* Copyright (c) 2006-2012 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
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#include "Channel.h"
+#include <map>
+#include <string>
+
+namespace love
+{
+namespace thread
+{
+	static std::map<std::string, Channel*> 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())
+		{
+			queue.front()->release();
+			queue.pop();
+		}
+
+		delete mutex;
+		delete cond;
+		if (named)
+		{
+			Lock l(namedChannelMutex);
+			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.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);
+		while (!queue.empty())
+		{
+			queue.front()->release();
+			queue.pop();
+		}
+
+		// Once again, release our own
+		// reference if we're named.
+		if (named)
+			release();
+	}
+} // thread
+} // love