00001
00002 #ifndef INCLUDED_MessageQueue_h_
00003 #define INCLUDED_MessageQueue_h_
00004
00005 #ifdef PLATFORM_APERIOS
00006 # warning MessageQueue is not Aperios compatable
00007 #else
00008
00009 #include "ListMemBuf.h"
00010 #include "RCRegion.h"
00011 #include "Shared/MarkScope.h"
00012 #include "Shared/attributes.h"
00013 #include <exception>
00014
00015 #include "Shared/TimeET.h"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 class MessageQueueBase {
00030 public:
00031
00032
00033 class MessageFilter {
00034 public:
00035
00036 virtual bool filterSendRequest(RCRegion* rcr)=0;
00037
00038 virtual ~MessageFilter() {}
00039 };
00040
00041
00042 MessageQueueBase()
00043 : lock(), overflowPolicy(THROW_BAD_ALLOC), isClosed(false), reportDroppings(false), numMessages(0),
00044 numReceivers(0), messagesRead(0)
00045 {
00046 for(unsigned int i=0; i<ProcessID::NumProcesses; ++i)
00047 filters[i]=NULL;
00048 }
00049
00050 virtual ~MessageQueueBase() {}
00051
00052
00053
00054
00055
00056
00057 typedef unsigned short index_t;
00058
00059
00060
00061 virtual SemaphoreManager::semid_t addReceiver() ATTR_must_check =0;
00062
00063 virtual void removeReceiver(SemaphoreManager::semid_t rcvr)=0;
00064
00065 virtual unsigned int getNumReceivers() const { return numReceivers; }
00066
00067
00068
00069
00070
00071
00072 virtual SemaphoreManager::semid_t addReadStatusListener() ATTR_must_check =0;
00073
00074 virtual void removeReadStatusListener(SemaphoreManager::semid_t sem)=0;
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 virtual void sendMessage(RCRegion * rcr, bool autoDereference=false)=0;
00091
00092
00093
00094
00095
00096 virtual RCRegion * readMessage(index_t msg, SemaphoreManager::semid_t rcvr)=0;
00097
00098
00099
00100 virtual RCRegion * peekMessage(index_t msg)=0;
00101
00102 virtual void markRead(index_t msg, SemaphoreManager::semid_t rcvr)=0;
00103
00104 virtual void close() { AutoLock autolock(lock); isClosed=true; }
00105
00106 virtual void setReportDroppings(bool report) { reportDroppings=report; }
00107 virtual bool getReportDroppings() const { return reportDroppings; }
00108
00109
00110
00111 virtual unsigned int getMessageSN(index_t msg)=0;
00112
00113
00114 virtual unsigned int getMessagesRead() { return messagesRead; }
00115
00116
00117 virtual unsigned int getMessagesSent() { return numMessages; }
00118
00119
00120 virtual unsigned int getMessagesUnread() { return getMessagesSent() - getMessagesRead(); }
00121
00122
00123 typedef MarkScope AutoLock;
00124
00125 MutexLock<ProcessID::NumProcesses>& getLock() const { return lock; }
00126
00127
00128 virtual index_t oldest() const=0;
00129 virtual index_t newer(index_t it) const=0;
00130 virtual index_t older(index_t it) const=0;
00131 virtual index_t newest() const=0;
00132 virtual bool isEnd(index_t it) const=0;
00133
00134
00135 enum OverflowPolicy_t {
00136 DROP_OLDEST,
00137 DROP_NEWEST,
00138 WAIT,
00139 THROW_BAD_ALLOC
00140 };
00141
00142 void setOverflowPolicy(OverflowPolicy_t op) { overflowPolicy=op; }
00143
00144 OverflowPolicy_t getOverflowPolicy() const { return overflowPolicy; }
00145
00146 static void setSemaphoreManager(SemaphoreManager* mgr) {
00147 semgr=mgr;
00148 }
00149 static SemaphoreManager* getSemaphoreManager() {
00150 return semgr;
00151 }
00152
00153
00154
00155 void addMessageFilter(MessageFilter& filter) {
00156 filters[ProcessID::getID()]=&filter;
00157 }
00158
00159 void removeMessageFilter() {
00160 filters[ProcessID::getID()]=NULL;
00161 }
00162 protected:
00163
00164 static SemaphoreManager* semgr;
00165
00166 mutable MutexLock<ProcessID::NumProcesses> lock;
00167 volatile OverflowPolicy_t overflowPolicy;
00168 bool isClosed;
00169 bool reportDroppings;
00170 unsigned int numMessages;
00171 unsigned int numReceivers;
00172 unsigned int messagesRead;
00173 MessageFilter* filters[ProcessID::NumProcesses];
00174 private:
00175 MessageQueueBase(const MessageQueueBase&);
00176 MessageQueueBase& operator=(const MessageQueueBase&);
00177 };
00178
00179
00180
00181
00182 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS=10, unsigned int MAX_SENDERS=10>
00183 class MessageQueue : public MessageQueueBase {
00184 public:
00185
00186 static const unsigned int CAPACITY=MAX_UNREAD;
00187
00188 static const unsigned int RECEIVER_CAPACITY=MAX_RECEIVERS;
00189
00190
00191
00192
00193 static const unsigned int SENDER_CAPACITY=MAX_SENDERS;
00194
00195
00196 MessageQueue() : MessageQueueBase(), mq(), rcvrs(), sndrs() {}
00197
00198
00199 virtual ~MessageQueue();
00200
00201 virtual SemaphoreManager::semid_t addReadStatusListener() ATTR_must_check;
00202 virtual void removeReadStatusListener(SemaphoreManager::semid_t sem);
00203
00204 virtual SemaphoreManager::semid_t addReceiver() ATTR_must_check;
00205 virtual void removeReceiver(SemaphoreManager::semid_t rcvr);
00206
00207 virtual void sendMessage(RCRegion * rcr, bool autoDereference=false);
00208 virtual RCRegion * readMessage(index_t msg, SemaphoreManager::semid_t rcvr);
00209 virtual RCRegion * peekMessage(index_t msg);
00210 virtual void markRead(index_t msg, SemaphoreManager::semid_t rcvr);
00211
00212 virtual unsigned int getMessageSN(index_t msg) { return mq[msg].sn; }
00213
00214 virtual index_t oldest() const { AutoLock autolock(lock); return mq.begin(); }
00215 virtual index_t newer(index_t it) const { AutoLock autolock(lock); return mq.next(it); }
00216 virtual index_t older(index_t it) const { AutoLock autolock(lock); return mq.prev(it); }
00217 virtual index_t newest() const { AutoLock autolock(lock); return mq.prev(mq.end()); }
00218 virtual bool isEnd(index_t it) const { AutoLock autolock(lock); return it==mq.end() || it>=mq_t::MAX_ENTRIES; }
00219
00220 protected:
00221
00222 struct entry {
00223 entry() : id(), sn(), numRead(0) { memset(readFlags,0,sizeof(readFlags)); }
00224 entry(unsigned int serialNumber, RCRegion* r)
00225 : id(r->ID()), sn(serialNumber), numRead(0) { memset(readFlags,0,sizeof(readFlags)); }
00226 RCRegion::Identifier id;
00227 unsigned int sn;
00228 bool readFlags[MAX_RECEIVERS];
00229 unsigned int numRead;
00230 };
00231
00232
00233 typedef ListMemBuf<entry,MAX_UNREAD,index_t> mq_t;
00234
00235 mq_t mq;
00236
00237
00238 typedef ListMemBuf<SemaphoreManager::semid_t,MAX_RECEIVERS,index_t> rcvrs_t;
00239
00240 rcvrs_t rcvrs;
00241
00242
00243 typename rcvrs_t::index_t lookupReceiver(SemaphoreManager::semid_t rcvr) const;
00244
00245
00246 typedef ListMemBuf<SemaphoreManager::semid_t,MAX_SENDERS,index_t> sndrs_t;
00247
00248 sndrs_t sndrs;
00249 };
00250
00251 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00252 MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::~MessageQueue() {
00253
00254
00255
00256 while(!mq.empty()) {
00257 RCRegion * rcr = RCRegion::attach(mq.front().id);
00258 rcr->RemoveSharedReference();
00259 rcr->RemoveReference();
00260 mq.pop_front();
00261 }
00262 }
00263
00264 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00265 SemaphoreManager::semid_t MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::addReadStatusListener() {
00266 AutoLock autolock(lock);
00267 SemaphoreManager::semid_t sem=semgr->getSemaphore();
00268 if(sem==semgr->invalid()) {
00269 std::cerr << "ERROR: unable to add read status listener to message queue because semaphore manager is out of semaphores" << std::endl;
00270 return semgr->invalid();
00271 }
00272 if(sndrs.push_back(sem)==sndrs.end()) {
00273 std::cerr << "ERROR: unable to add read status listener to message queue because message queue can't register any more senders (MAX_SENDERS)" << std::endl;
00274 semgr->releaseSemaphore(sem);
00275 return semgr->invalid();
00276 }
00277 return sem;
00278 }
00279
00280 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00281 void MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::removeReadStatusListener(SemaphoreManager::semid_t sem) {
00282 AutoLock autolock(lock);
00283 for(index_t it=sndrs.begin(); it!=sndrs.end(); it=sndrs.next(it))
00284 if(sndrs[it]==sem) {
00285 sndrs.erase(it);
00286 semgr->releaseSemaphore(sem);
00287 break;
00288 }
00289 }
00290
00291 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00292 SemaphoreManager::semid_t MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::addReceiver() {
00293 AutoLock autolock(lock);
00294 SemaphoreManager::semid_t sem=semgr->getSemaphore();
00295 if(sem==semgr->invalid()) {
00296 std::cerr << "ERROR: unable to add receiver to message queue because semaphore manager is out of semaphores" << std::endl;
00297 return semgr->invalid();
00298 }
00299 if(rcvrs.push_back(sem)==rcvrs.end()) {
00300 std::cerr << "ERROR: unable to add receiver to message queue because message queue can't register any more receivers (MAX_RECEIVERS)" << std::endl;
00301 semgr->releaseSemaphore(sem);
00302 return semgr->invalid();
00303 }
00304 numReceivers++;
00305 return sem;
00306 }
00307
00308 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00309 void MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::removeReceiver(SemaphoreManager::semid_t rcvr) {
00310 AutoLock autolock(lock);
00311 index_t rcvr_id=rcvrs.begin();
00312 for(; rcvr_id!=rcvrs.end(); rcvr_id=rcvrs.next(rcvr_id))
00313 if(rcvrs[rcvr_id]==rcvr)
00314 break;
00315 if(rcvr_id==rcvrs.end()) {
00316 std::cerr << "WARNING: tried to remove message queue receiver " << rcvr << ", which is not registered as a receiver for this queue" << std::endl;
00317 return;
00318 }
00319 rcvrs.erase(rcvr_id);
00320 semgr->releaseSemaphore(rcvr);
00321 numReceivers--;
00322 for(index_t it=mq.begin(); it!=mq.end(); it=mq.next(it)) {
00323 if(mq[it].readFlags[rcvr_id]) {
00324
00325 mq[it].readFlags[rcvr_id]=false;
00326 mq[it].numRead--;
00327 } else if(mq[it].numRead==numReceivers) {
00328
00329 RCRegion * rcr = RCRegion::attach(mq[it].id);
00330 rcr->RemoveSharedReference();
00331 rcr->RemoveReference();
00332 it=mq.prev(it);
00333 mq.erase(mq.next(it));
00334 messagesRead++;
00335 for(index_t sit=sndrs.begin(); sit!=sndrs.end(); sit=sndrs.next(sit))
00336 semgr->raise(sndrs[sit],1);
00337 }
00338 }
00339 }
00340
00341 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00342 void MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::sendMessage(RCRegion * rcr, bool autoDereference) {
00343 AutoLock autolock(lock);
00344 if(rcr==NULL) {
00345 rcr=new RCRegion(0);
00346 autoDereference=true;
00347 }
00348 if(filters[ProcessID::getID()]!=NULL && !filters[ProcessID::getID()]->filterSendRequest(rcr))
00349 return;
00350 if(numReceivers==0) {
00351
00352
00353 messagesRead++;
00354 for(index_t sit=sndrs.begin(); sit!=sndrs.end(); sit=sndrs.next(sit))
00355 semgr->raise(sndrs[sit],1);
00356 return;
00357 }
00358 if(isClosed) {
00359 if(reportDroppings)
00360 std::cerr << "Warning: MessageQueue dropping " << rcr->ID().key << " because queue is closed" << std::endl;
00361 return;
00362 }
00363 if(mq.size()==mq.getMaxCapacity()) {
00364 switch(overflowPolicy) {
00365 case DROP_OLDEST: {
00366 if(reportDroppings)
00367 std::cerr << "WARNING: MessageQueue full, dropping oldest unread message (" << mq.front().id.key << ")" << std::endl;
00368 RCRegion * eldest = RCRegion::attach(mq.front().id);
00369 eldest->RemoveSharedReference();
00370 mq.pop_front();
00371 eldest->RemoveReference();
00372 } break;
00373 case DROP_NEWEST:
00374 if(reportDroppings)
00375 std::cerr << "WARNING: MessageQueue full, dropping newest unread message (" << rcr->ID().key << ")" << std::endl;
00376 return;
00377 case WAIT:
00378 if(reportDroppings)
00379 std::cerr << "WARNING: MessageQueue full, waiting for readers to catch up" << std::endl;
00380 while(mq.size()==mq.getMaxCapacity()) {
00381
00382 unsigned int ll=lock.get_lock_level();
00383 lock.releaseAll();
00384 usleep(MutexLockBase::usleep_granularity*15);
00385 for(unsigned int i=0; i<ll; i++)
00386 lock.lock(ProcessID::getID());
00387 if(overflowPolicy!=WAIT) {
00388 sendMessage(rcr);
00389 return;
00390 }
00391 }
00392 break;
00393 case THROW_BAD_ALLOC:
00394 if(reportDroppings)
00395 std::cerr << "WARNING: MessageQueue full, throwing bad_alloc exception" << std::endl;
00396 throw std::bad_alloc();
00397 break;
00398 }
00399 }
00400 rcr->AddSharedReference();
00401 if(mq.push_back(entry(numMessages++,rcr))==mq.end()) {
00402
00403 std::cerr << "ERROR: MessageQueue unable to add message; buggy overflow policy?" << std::endl;
00404 exit(EXIT_FAILURE);
00405 }
00406
00407
00408
00409 for(index_t it=rcvrs.begin(); it!=rcvrs.end(); it=rcvrs.next(it))
00410 semgr->raise(rcvrs[it],1);
00411
00412 if(autoDereference)
00413 rcr->RemoveReference();
00414 }
00415
00416 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00417 RCRegion * MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::readMessage(index_t msg, SemaphoreManager::semid_t rcvr) {
00418 AutoLock autolock(lock);
00419 RCRegion * rcr = RCRegion::attach(mq[msg].id);
00420 index_t rcvr_id=lookupReceiver(rcvr);
00421 if(rcvr_id==rcvrs.end())
00422 return rcr;
00423 if(mq[msg].readFlags[rcvr_id]) {
00424 std::cerr << "WARNING: MessageQueue::readMessage(): Receiver re-reading message, could be recycled/invalidated any time" << std::endl;
00425 return rcr;
00426 }
00427 mq[msg].readFlags[rcvr_id]=true;
00428 mq[msg].numRead++;
00429 if(mq[msg].numRead==numReceivers) {
00430
00431 rcr->RemoveSharedReference();
00432 mq.erase(msg);
00433 messagesRead++;
00434 for(index_t sit=sndrs.begin(); sit!=sndrs.end(); sit=sndrs.next(sit))
00435 semgr->raise(sndrs[sit],1);
00436 }
00437 return rcr;
00438 }
00439
00440 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00441 RCRegion * MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::peekMessage(index_t msg) {
00442
00443 return RCRegion::attach(mq[msg].id);
00444 }
00445
00446 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00447 void MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::markRead(index_t msg, SemaphoreManager::semid_t rcvr) {
00448 AutoLock autolock(lock);
00449 index_t rcvr_id=lookupReceiver(rcvr);
00450 if(rcvr_id==rcvrs.end())
00451 return;
00452 if(mq[msg].readFlags[rcvr_id]) {
00453 std::cerr << "WARNING: MessageQueue::markRead(): Receiver re-reading message, could be recycled/invalidated any time" << std::endl;
00454 return;
00455 }
00456 mq[msg].readFlags[rcvr_id]=true;
00457 mq[msg].numRead++;
00458 if(mq[msg].numRead==numReceivers) {
00459
00460 RCRegion * rcr = RCRegion::attach(mq[msg].id);
00461 rcr->RemoveSharedReference();
00462 rcr->RemoveReference();
00463 mq.erase(msg);
00464 messagesRead++;
00465 for(index_t sit=sndrs.begin(); sit!=sndrs.end(); sit=sndrs.next(sit))
00466 semgr->raise(sndrs[sit],1);
00467 }
00468 }
00469
00470 template<unsigned int MAX_UNREAD, unsigned int MAX_RECEIVERS, unsigned int MAX_SENDERS>
00471 typename MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::rcvrs_t::index_t
00472 MessageQueue<MAX_UNREAD,MAX_RECEIVERS,MAX_SENDERS>::lookupReceiver(SemaphoreManager::semid_t rcvr) const {
00473 for(index_t rcvr_id=rcvrs.begin(); rcvr_id!=rcvrs.end(); rcvr_id=rcvrs.next(rcvr_id))
00474 if(rcvrs[rcvr_id]==rcvr)
00475 return rcvr_id;
00476 std::cerr << "WARNING: tried to look up queue receiver " << rcvr << ", which is not registered as a receiver for this queue" << std::endl;
00477 return rcvrs.end();
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 #endif //APERIOS check
00492
00493 #endif //INCLUDED