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