00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef LIBMUTH_CHANNEL_H
00020 #define LIBMUTH_CHANNEL_H
00021
00022 #ifdef __WIN32__
00023
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
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
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