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 assert(this->manager.waiter == NULL);
00069 this->manager.waiter = &getcurrentthread();
00070 this->manager.datalock.release();
00071 this->manager.waiter->delayme();
00072
00073 assert(this->manager.datalock.tryacquire() == false);
00074 this->manager.waiter = NULL;
00075 }
00076 assert(this->messageid != std::numeric_limits<MessageID>::max());
00077 assert(this->queue.empty() == false);
00078
00079 const T result((std::auto_ptr<std::pair<MessageID,T> >
00080 (this->queue.front()))->second);
00081 this->queue.pop();
00082 if(this->queue.empty())
00083 this->messageid = std::numeric_limits<MessageID>::max();
00084 else
00085 this->messageid = this->queue.front()->first;
00086 return result;
00087 }
00088
00089 template<class T> inline bool Channel<T>::isempty() const {
00090 return this->messageid == std::numeric_limits<MessageID>::max();
00091 }
00092
00093 inline ChannelGroup::ChannelGroup(ChannelManager &m) : manager(m) {
00094 }
00095
00096 #endif