Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

MessageReceiver.cc

Go to the documentation of this file.
00001 #ifndef PLATFORM_APERIOS
00002 
00003 #include "MessageReceiver.h"
00004 //#include "local/sim/Process.h"
00005 //#include <iostream>
00006 //using namespace std;
00007 
00008 MessageReceiver::MessageReceiver(MessageQueueBase& mq, bool (*callback) (RCRegion*)/*=NULL*/, bool startThread/*=true*/)
00009 : Thread(), queue(mq), nextMessage(0), lastProcessedMessage(-1U), process(callback), sleeptime(1000), curit((index_t)-1)
00010 {
00011   queue.addReceiver();
00012   if(startThread)
00013     start();
00014 }
00015 
00016 MessageReceiver::~MessageReceiver() {
00017   if(isRunning())
00018     queue.removeReceiver();
00019 }
00020 
00021 RCRegion * MessageReceiver::peekNextMessage() {
00022   MessageQueueBase::AutoLock autolock(queue.getLock());
00023   if(queue.isEnd(curit)) {
00024     index_t it=queue.newest(); //start with the newest
00025     while(!queue.isEnd(it) && queue.getMessageSN(it)>=nextMessage)
00026       it=queue.older(it); //scan back to the first already read by this process
00027     curit=it=queue.newer(it); //go to the following one (first unread)
00028   }
00029   if(queue.isEnd(curit))
00030     return NULL;
00031   return queue.peekMessage(curit);
00032 }
00033 
00034 RCRegion * MessageReceiver::getNextMessage() {
00035   MessageQueueBase::AutoLock autolock(queue.getLock());
00036   index_t it; //will be set to the current message to return; curit will be set to the following message
00037   if(queue.isEnd(curit)) {
00038     it=queue.newest(); //start with the newest
00039     while(!queue.isEnd(it) && queue.getMessageSN(it)>=nextMessage)
00040       it=queue.older(it); //scan back to the first already read by this process
00041     curit=it=queue.newer(it); //go to the following one (first unread)
00042   } else {
00043     it=curit;
00044     while(!queue.isEnd(it) && queue.getMessageSN(it)<nextMessage)
00045       it=queue.newer(it); //scan forward to next message not read by this process
00046     curit=it;
00047   }
00048   if(queue.isEnd(it))
00049     return NULL;
00050   nextMessage=queue.getMessageSN(it)+1;
00051   curit=queue.newer(it); //next time, start on (or peek at) the one after this
00052   return queue.readMessage(it);
00053 }
00054 
00055 void MessageReceiver::markRead() {
00056   if(queue.isEnd(curit))
00057     return;
00058   nextMessage=queue.getMessageSN(curit)+1;
00059   queue.markRead(curit);
00060   curit=queue.newer(curit); //next time, start on (or peek at) the one after this
00061 }
00062 
00063 void MessageReceiver::waitNextMessage() {
00064   for(;;) {
00065     RCRegion * ans=peekNextMessage();
00066     if(ans!=NULL)
00067       return;
00068     usleep(sleeptime);
00069   }
00070 }
00071 
00072 unsigned int MessageReceiver::runloop() {
00073   RCRegion * msg;
00074   //cout << Process::getName() << " runloop" << endl;
00075   while((msg=peekNextMessage())!=NULL) {
00076     //cout << Process::getName() << " got " << msg->ID().key << ' ' << lastProcessedMessage << ' ' << queue.getMessageSN(curit) << ' ' << curit << endl;
00077     bool used=false;
00078     if(lastProcessedMessage!=queue.getMessageSN(curit)) {
00079       //cout << Process::getName() << " process" << endl;
00080       lastProcessedMessage=queue.getMessageSN(curit);
00081       used=process(msg);
00082       if(used)
00083         markRead(); // message was consumed, mark it read so next peek will get the next
00084       //cout << used << ' ' << curit;
00085       //if(!queue.isEnd(curit))
00086       //cout << lastProcessedMessage << ' ' << queue.getMessageSN(curit);
00087       //cout << endl;
00088     }
00089     msg->RemoveReference();
00090     if(!used) //have to break out of the loop to sleep & check interrupts -- otherwise we'll busyloop peeking at the same message
00091       break;
00092   }
00093   return sleeptime;
00094 }
00095 
00096 void MessageReceiver::finish() {
00097   if(!isRunning())
00098     return;
00099   stop();
00100   join();
00101   RCRegion * msg;
00102   //cout << Process::getName() << " finish" << endl;
00103   while((msg=peekNextMessage())!=NULL) {
00104     //cout << Process::getName() << " got " << msg->ID().key << ' ' << lastProcessedMessage << ' ' << queue.getMessageSN(curit) << ' ' << curit << endl;
00105     bool used=false;
00106     if(lastProcessedMessage!=queue.getMessageSN(curit)) {
00107       //cout << Process::getName() << " process" << endl;
00108       lastProcessedMessage=queue.getMessageSN(curit);
00109       used=process(msg);
00110       if(used)
00111         markRead(); // message was consumed, mark it read so next peek will get the next
00112       //cout << used << ' ' << curit;
00113       //if(!queue.isEnd(curit))
00114       //cout << lastProcessedMessage << ' ' << queue.getMessageSN(curit);
00115       //cout << endl;
00116     }
00117     msg->RemoveReference();
00118     if(!used) // if the consumer can't process immediately, we're not waiting around -- drop the rest
00119       break;
00120   }
00121   queue.removeReceiver();
00122 }
00123 
00124 
00125 /*! @file
00126  * @brief 
00127  * @author Ethan Tira-Thompson (ejt) (Creator)
00128  *
00129  * $Author: ejt $
00130  * $Name: tekkotsu-2_4_1 $
00131  * $Revision: 1.7 $
00132  * $State: Exp $
00133  * $Date: 2005/07/28 18:22:16 $
00134  */
00135 
00136 #endif //PLATFORM_APERIOS check (aperios doesn't support pthreads...)

Tekkotsu v2.4.1
Generated Tue Aug 16 16:32:47 2005 by Doxygen 1.4.4