channel.h

00001 /*
00002  *  Copyright (C) 2006  Helmut Grohne
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 #ifndef LIBMUTH_CHANNEL_H
00020 #define LIBMUTH_CHANNEL_H
00021 
00022 #ifdef __WIN32__
00023 /* repair min and max */
00024 #include "win32.h"
00025 #endif
00026 #include <limits>
00027 #include <memory>
00028 #include <assert.h>
00029 #include "channel_decls.h"
00030 #include "microthread.h"
00031 #include "currentthread.h"
00032 
00033 inline MessageID ChannelManager::genid() {
00034         assert(this->datalock.tryacquire() == false);
00035         return this->lastid++;
00036 }
00037 
00038 inline ChannelManager::ChannelManager() : lastid(0), waiter(NULL) {
00039 }
00040 
00041 inline BaseChannel::BaseChannel(ChannelManager &m)
00042                 : manager(m), messageid(std::numeric_limits<MessageID>::max()) {
00043 }
00044 
00045 inline MessageID BaseChannel::nextid() const {
00046         return this->messageid;
00047 }
00048 
00049 template<class T> inline Channel<T>::Channel(ChannelManager &m)
00050                 : BaseChannel(m) {
00051 }
00052 
00053 template<class T> void Channel<T>::send(T data) {
00054         this->manager.datalock.acquire();
00055         const MessageID msgid(this->manager.genid());
00056         this->queue.push(new std::pair<MessageID,T>(msgid, data));
00057         if(this->messageid == std::numeric_limits<MessageID>::max()) {
00058                 this->messageid = msgid;
00059                 /* Expects the lock to be acquired and releases it. */
00060                 this->manager.notify();
00061         } else
00062                 this->manager.datalock.release();
00063 }
00064 
00065 template<class T> T Channel<T>::receive() {
00066         WITHACQUIRED(this->manager.datalock);
00067         if(this->messageid == std::numeric_limits<MessageID>::max())
00068                 this->waitformessage();
00069         assert(this->messageid != std::numeric_limits<MessageID>::max());
00070         assert(this->queue.empty() == false);
00071         /* Credits to ##C++. */
00072         const T result((std::auto_ptr<std::pair<MessageID,T> >
00073                         (this->queue.front()))->second);
00074         this->queue.pop();
00075         if(this->queue.empty())
00076                 this->messageid = std::numeric_limits<MessageID>::max();
00077         else
00078                 this->messageid = this->queue.front()->first;
00079         return result;
00080 }
00081 
00082 template<class T> inline bool Channel<T>::isempty() const {
00083         return this->messageid == std::numeric_limits<MessageID>::max();
00084 }
00085 
00086 inline ChannelGroup::ChannelGroup(ChannelManager &m) : manager(m) {
00087 }
00088 
00089 #endif

Generated on Sat Feb 7 01:26:50 2009 by  doxygen 1.5.1