00001 #ifndef PLATFORM_APERIOS
00002
00003 #include "MessageReceiver.h"
00004 #include "Shared/debuget.h"
00005
00006
00007
00008
00009 MessageReceiver::MessageReceiver(MessageQueueBase& mq, bool (*callback) (RCRegion*), bool startThread, bool subscribe)
00010 : Thread(), queue(mq), semid(mq.getSemaphoreManager()->invalid()),
00011 nextMessage(0), lastProcessedMessage(-1U), process(callback), curit((index_t)-1)
00012 {
00013 if(startThread)
00014 start();
00015 else if(subscribe) {
00016 ASSERTRET(semid==queue.getSemaphoreManager()->invalid(),"semid is already set?");
00017 semid=queue.addReceiver();
00018 if(semid==queue.getSemaphoreManager()->invalid())
00019 std::cerr << "ERROR: could not start MessageReceiver -- out of semaphore IDs" << std::endl;
00020 }
00021 }
00022
00023 MessageReceiver::~MessageReceiver() {
00024 if(!isStarted())
00025 return;
00026 stop();
00027 join();
00028 queue.removeReceiver(semid);
00029 semid=queue.getSemaphoreManager()->invalid();
00030 }
00031
00032 RCRegion * MessageReceiver::peekNextMessage() {
00033 MessageQueueBase::AutoLock autolock(queue.getLock());
00034 findCurrentMessage();
00035 if(queue.isEnd(curit))
00036 return NULL;
00037 return queue.peekMessage(curit);
00038 }
00039
00040 RCRegion * MessageReceiver::getNextMessage() {
00041 MessageQueueBase::AutoLock autolock(queue.getLock());
00042 findCurrentMessage();
00043 if(queue.isEnd(curit))
00044 return NULL;
00045 nextMessage=queue.getMessageSN(curit)+1;
00046 curit=queue.newer(curit);
00047 return queue.readMessage(curit,semid);
00048 }
00049
00050 void MessageReceiver::stop() {
00051 Thread::stop();
00052 queue.getSemaphoreManager()->raise(semid,1);
00053 }
00054
00055 void MessageReceiver::findCurrentMessage() {
00056 if(queue.isEnd(curit)) {
00057 curit=queue.newest();
00058 while(!queue.isEnd(curit) && queue.getMessageSN(curit)>=nextMessage)
00059 curit=queue.older(curit);
00060 curit=queue.newer(curit);
00061 } else {
00062 while(!queue.isEnd(curit) && queue.getMessageSN(curit)<nextMessage)
00063 curit=queue.newer(curit);
00064 }
00065 }
00066
00067 void MessageReceiver::finish() {
00068 if(isStarted()) {
00069 stop();
00070 join();
00071 }
00072 if(semid!=queue.getSemaphoreManager()->invalid()) {
00073
00074 while(processNextMessage()) {}
00075 queue.removeReceiver(semid);
00076 semid=queue.getSemaphoreManager()->invalid();
00077 }
00078 }
00079
00080 bool MessageReceiver::launched() {
00081 if(semid==queue.getSemaphoreManager()->invalid())
00082 semid=queue.addReceiver();
00083 if(semid==queue.getSemaphoreManager()->invalid()) {
00084 std::cerr << "ERROR: could not start MessageReceiver -- out of semaphore IDs" << std::endl;
00085 return false;
00086 }
00087 return Thread::launched();
00088 }
00089
00090 unsigned int MessageReceiver::runloop() {
00091
00092 pushNoCancel();
00093 waitNextMessage();
00094 while(processNextMessage()) {
00095 queue.getSemaphoreManager()->lower(semid,1,false);
00096 }
00097 popNoCancel();
00098 return 0;
00099 }
00100
00101 bool MessageReceiver::waitNextMessage() {
00102 return queue.getSemaphoreManager()->lower(semid,1,true);
00103 }
00104
00105 bool MessageReceiver::processNextMessage() {
00106 RCRegion * msg=peekNextMessage();
00107 if(msg==NULL)
00108 return false;
00109
00110 bool used=false;
00111 if(lastProcessedMessage!=queue.getMessageSN(curit)) {
00112 lastProcessedMessage=queue.getMessageSN(curit);
00113
00114 used=process(msg);
00115 if(used)
00116 markRead(false);
00117
00118
00119
00120
00121 }
00122 msg->RemoveReference();
00123 return used;
00124 }
00125
00126 void MessageReceiver::markRead(bool checkNext) {
00127 findCurrentMessage();
00128 if(queue.isEnd(curit))
00129 return;
00130 nextMessage=queue.getMessageSN(curit)+1;
00131 queue.markRead(curit,semid);
00132 curit=queue.newer(curit);
00133 if(checkNext && !queue.isEnd(curit))
00134 queue.getSemaphoreManager()->raise(semid,1);
00135 }
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 #endif //PLATFORM_APERIOS check (aperios doesn't support pthreads...)