Blackboard.cc

00001 #include "Blackboard.h"
00002 #include <assert.h>
00003 
00004 Define_Module(Blackboard);
00005 
00006 std::ostream& operator<<(std::ostream& os, const Blackboard::SubscriberVector& v)
00007 {
00008     os << v.size() << " client(s) ";
00009     Blackboard::SubscriberVector::const_iterator it;
00010     for (it = v.begin(); it != v.end(); ++it)
00011     {
00012         os << (it == v.begin() ? ": " : ", ");
00013         if (dynamic_cast<cModule*>((*it).client))
00014         {
00015             cModule *mod = dynamic_cast<cModule*>((*it).client);
00016             os << "mod (" << mod->getClassName() << ") " << mod->getFullName() << " id=" << mod->getId();
00017         }
00018         else if (dynamic_cast<cObject*>((*it).client))
00019         {
00020             cObject *obj = dynamic_cast<cObject*>((*it).client);
00021             os << "a " << obj->getClassName();
00022         }
00023         else
00024         {
00025             os << "a " << opp_typename(typeid((*it).client));
00026         }
00027         os << " scope: " << (*it).scopeModuleId;
00028     }
00029     return os;
00030 }
00031 
00032 
00033 
00034 Blackboard::~Blackboard()
00035 {
00036 }
00037 
00038 void Blackboard::initialize(int stage) {
00039 
00040   if (stage == 0) {
00041     hasPar("coreDebug") ? coreDebug = par("coreDebug").boolValue() : coreDebug = false;
00042 
00043     WATCH_VECTOR(clientVector);
00044       WATCH_VECTOR(categoryDescriptions);
00045   }
00046 }
00047 
00048 void Blackboard::handleMessage(cMessage *msg) {
00049   error("This module does not handle any messages yet");
00050 }
00051 
00052 const char* Blackboard::categoryName(int category)
00053 {
00054     if(categoryDescriptions.size() < static_cast<unsigned>(category)) {
00055         error("BlackBoard::categoryName called with unknown category (%i)", category);
00056     }
00057     return categoryDescriptions[category];
00058 }
00059 
00060 int Blackboard::findAndCreateDescription(bool *isNewEntry, const BBItem *category)
00061 {
00062 
00063     CategoryDescriptions::size_type it;
00064     std::string desc = category->getClassName();
00065     std::string cName;
00066 
00067     for(it = 0; it < categoryDescriptions.size(); ++it)
00068     {
00069         cName = categoryDescriptions[it];
00070         if(cName == desc) {
00071             (*isNewEntry) = false;
00072             break;
00073         }
00074     }
00075     if(it == categoryDescriptions.size()) {
00076         (*isNewEntry) = true;
00077         categoryDescriptions.push_back(category->getClassName());
00078         it = categoryDescriptions.size() - 1;
00079         clientVector.push_back(SubscriberVector());
00080         if(it != clientVector.size()-1)
00081             error("BlackBoard::findAndCreateDescription SubscriberVector creation failed");
00082         parentVector.push_back(-1);
00083         if(it != parentVector.size()-1)
00084             error("BlackBoard::findAndCreateDescription ParentVector creation failed");
00085         nextCategory = categoryDescriptions.size();
00086     }
00087     return static_cast<int>(it);
00088 }
00089 
00090 void Blackboard::fillParentVector(const BBItem *category, int cat)
00091 {
00092     bool isNewEntry = true;
00093     int it;
00094 
00095     BBItem *parentObject;
00096     BBItem base;
00097 
00098     parentObject = category->parentObject();
00099 
00100     if(typeid(*parentObject) != typeid(base)) {
00101         it = findAndCreateDescription(&isNewEntry, parentObject);
00102         parentVector[cat] = it;
00103         fillParentVector(parentObject, it);
00104     }
00105     delete parentObject;
00106 }
00107 
00108 
00109 
00110 int Blackboard::subscribe(ImNotifiable *client, int category, int scopeModuleId)
00111 {
00112     if(coreDebug) {
00113         Enter_Method("subscribe(%s, %i)", categoryName(category), scopeModuleId);
00114     } else {
00115         Enter_Method_Silent();
00116     }
00117 
00118     // find or create entry for this category
00119     SubscriberVector& clients = clientVector[category];
00120     SubscriberVector::const_iterator it;
00121     for(it = clients.begin(); it != clients.end(); ++it) {
00122         if((*it).client == client) {
00123             std::string cname("unkown");
00124             cModule *cm = dynamic_cast<cModule *>(client);
00125             if(cm) cname = cm->getFullPath();
00126             error("BlackBoard::subscribe called twice for item %s, by client %s. \nThis probably means that a class from which you derived yours has \nalready subscribed to this item. This may result in conflicts, please check.\n ", categoryName(category), cname.c_str());
00127             break;
00128         }
00129     }
00130     // add client if not already there
00131     if (it == clients.end()) {
00132         clients.push_back(Subscriber(client, scopeModuleId));
00133     }
00134     return category;
00135 }
00136 
00137 int Blackboard::subscribe(ImNotifiable *client, const BBItem *category, int scopeModuleId)
00138 {
00139     if(coreDebug) {
00140         Enter_Method("subscribe(%s, %i)", category?category->getClassName() : "n/a",
00141                      scopeModuleId);
00142     } else {
00143         Enter_Method_Silent();
00144     }
00145     CategoryDescriptions::size_type it = 0;
00146     bool isNewEntry;
00147 
00148     if(category) {
00149         it = findAndCreateDescription(&isNewEntry, category);
00150         if(isNewEntry) fillParentVector(category, static_cast<int>(it));
00151         subscribe(client, static_cast<int>(it), scopeModuleId);
00152     }
00153     else {
00154         error("BlackBoard::subscribe called without category item");
00155     }
00156     return static_cast<int>(it);
00157 }
00158 
00159 void Blackboard::unsubscribe(ImNotifiable *client, int category)
00160 {
00161     if(coreDebug) {
00162         Enter_Method("unsubscribe(%s)", categoryName(category));
00163     } else {
00164         Enter_Method_Silent();
00165     }
00166     // find (or create) entry for this category
00167     SubscriberVector& clients = clientVector[category];
00168 
00169     // remove client if there
00170     SubscriberVector::iterator it;
00171     // go through the clients
00172     for(it = clients.begin(); it != clients.end(); ++it)
00173     {
00174         // check if client to be unsubscribed was found
00175       if((*it).client == client)
00176       {
00177         // client found, unsubscribe client and end search
00178         clients.erase(it);
00179       break;
00180       }
00181     }
00182 }
00183 
00184 void Blackboard::publishBBItem(int category, const BBItem *details, int scopeModuleId)
00185 {
00186     if(coreDebug) {
00187         Enter_Method("publish(%s, %s, %i)", categoryName(category),
00188                      details?details->info().c_str() : "n/a", scopeModuleId);
00189     } else {
00190         Enter_Method_Silent();
00191     }
00192 
00193     int pCat;
00194     if(clientVector.size() > 0) {
00195         SubscriberVector::const_iterator j;
00196         for (j=clientVector[category].begin(); j!=clientVector[category].end(); ++j)
00197         {
00198             if(((*j).scopeModuleId == -1) || ((*j).scopeModuleId == scopeModuleId))
00199             {
00200                 (*j).client->receiveBBItem(category, details, scopeModuleId);
00201             }
00202         }
00203         pCat = parentVector[category];
00204         if(pCat >= 0) publishBBItem(pCat, details, scopeModuleId);
00205     }
00206 }
00207 
00208 int Blackboard::getCategory(const BBItem *details)
00209 {
00210     if(coreDebug) {
00211         Enter_Method("getCategory(%s)", details?details->getClassName():"n/a");
00212     } else {
00213         Enter_Method_Silent();
00214     }
00215     int category = -1;
00216     bool isNewEntry;
00217 
00218     if(details) {
00219         category = findAndCreateDescription(&isNewEntry, details);
00220         if(isNewEntry) fillParentVector(details, category);
00221     } else {
00222         error("BlackBoard::getCategory called without category item");
00223     }
00224     return category;
00225 }
00226 
00227 //BB end
00228