INET Framework for OMNeT++/OMNEST
Blackboard.cc
Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2004 Andras Varga
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 
00019 #include <algorithm>
00020 #include "Blackboard.h"
00021 #include "ModuleAccess.h"
00022 
00023 Define_Module(Blackboard);
00024 
00025 
00026 #define coreEV (ev.isDisabled()||!coreDebug) ? ev : ev <<getParentModule()->getName()<<"["<<getParentModule()->getIndex()<<"]::Blackboard: "
00027 
00028 
00029 std::ostream& operator<<(std::ostream& os, const Blackboard::BBItem& bbi)
00030 {
00031     os << bbi.getData()->info();
00032     return os;
00033 }
00034 
00035 Blackboard::Blackboard()
00036 {
00037 }
00038 
00039 Blackboard::~Blackboard()
00040 {
00041     while (!contents.empty())
00042     {
00043         ContentsMap::iterator i = contents.begin();
00044         delete (*i).second;
00045         contents.erase(i);
00046     }
00047 }
00048 
00049 void Blackboard::initialize()
00050 {
00051   if(hasPar("coreDebug"))
00052     coreDebug = par("coreDebug").boolValue();
00053   else
00054     coreDebug = false;
00055     WATCH_PTRMAP(contents);
00056 }
00057 
00058 void Blackboard::handleMessage(cMessage *msg)
00059 {
00060     error("Blackboard doesn't handle messages, it can be accessed via direct method calls");
00061 }
00062 
00063 BBItemRef Blackboard::publish(const char *label, cPolymorphic *item)
00064 {
00065     Enter_Method("publish(\"%s\", %s *ptr)", label, item->getClassName());
00066 
00067     // check uniqueness of label
00068     ContentsMap::iterator k = contents.find(std::string(label));
00069     if (k!=contents.end())
00070         error("publish(): blackboard already contains an item with label `%s'", label);
00071 
00072     // add to BB contents
00073     BBItem *bbitem = new BBItem();
00074     bbitem->_item = item;
00075     bbitem->_label = label;
00076     contents[bbitem->_label] = bbitem;
00077 
00078     coreEV <<"publish "<<label<<" on bb\n";
00079     coreEV <<"bbItem->label: "<<bbitem->getLabel()<<endl;
00080     // notify
00081     SubscriberVector& vec = registeredClients;
00082     for (SubscriberVector::iterator i=vec.begin(); i!=vec.end(); ++i){
00083         (*i)->blackboardItemPublished(bbitem);
00084     }
00085     return bbitem;
00086 }
00087 
00088 void Blackboard::withdraw(BBItemRef bbItem)
00089 {
00090     Enter_Method("withdraw(\"%s\")", bbItem->getLabel());
00091 
00092     // find on BB
00093     ContentsMap::iterator k = contents.find(bbItem->_label);
00094     if (k==contents.end())
00095       error("withdraw(): item labelled `%s' is not on clipboard (BBItemRef stale?)", bbItem->_label.c_str());
00096 
00097     // notify subscribers
00098     SubscriberVector& vec = bbItem->subscribers;
00099     for (SubscriberVector::iterator i=vec.begin(); i!=vec.end(); ++i)
00100         (*i)->blackboardItemWithdrawn(bbItem);
00101 
00102     // remove
00103     contents.erase(k);
00104     bbItem->_item = NULL; // may make bogus code crash sooner
00105     delete bbItem;
00106 }
00107 
00108 void Blackboard::changed(BBItemRef bbItem, cPolymorphic *item)
00109 {
00110   coreEV <<"enter changed; item: "<<bbItem->getLabel()<<" changed -> notify subscribers\n";
00111 
00112   Enter_Method("changed(\"%s\", %s *ptr)", bbItem->getLabel(), item->getClassName());
00113 
00114     // update data pointer
00115     if (item)
00116         bbItem->_item = item;
00117     // notify subscribers
00118     SubscriberVector& vec = bbItem->subscribers;
00119     for (SubscriberVector::iterator i=vec.begin(); i!=vec.end(); ++i){
00120         (*i)->blackboardItemChanged(bbItem);
00121     }
00122 }
00123 
00124 BBItemRef Blackboard::subscribe(BlackboardAccess *bbClient, const char *label)
00125 {
00126     Enter_Method("subscribe(this,\"%s\")", label);
00127 
00128     // look up item by label
00129     BBItemRef item = find(label);
00130     if (!item)
00131        error("subscribe(): item labelled `%s' not on blackboard", label);
00132 
00133     // subscribe
00134     coreEV <<"subscribe for "<<label<<" on bb\n";
00135     subscribe(bbClient, item);
00136     return item;
00137 }
00138 
00139 BBItemRef Blackboard::find(const char *label)
00140 {
00141     ContentsMap::iterator k = contents.find(std::string(label));
00142     return k==contents.end() ? NULL : (*k).second;
00143 }
00144 
00145 BBItemRef Blackboard::subscribe(BlackboardAccess *bbClient, BBItemRef bbItem)
00146 {
00147     Enter_Method("subscribe(this,\"%s\")", bbItem->getLabel());
00148 
00149     // check if already subscribed
00150     SubscriberVector& vec = bbItem->subscribers;
00151     if (std::find(vec.begin(), vec.end(), bbClient)!=vec.end())
00152         return bbItem; // already subscribed
00153 
00154     // add subscriber
00155     vec.push_back(bbClient);
00156 
00157     coreEV <<"sucessfully subscribed for item: "<<bbItem->getLabel()<<endl;
00158     return bbItem;
00159 }
00160 
00161 void Blackboard::unsubscribe(BlackboardAccess *bbClient, BBItemRef bbItem)
00162 {
00163     Enter_Method("unsubscribe(this,\"%s\")", bbItem->getLabel());
00164 
00165     // check if already subscribed
00166     SubscriberVector& vec = bbItem->subscribers;
00167     SubscriberVector::iterator k = std::find(vec.begin(), vec.end(), bbClient);
00168     if (k==vec.end())
00169         return; // ok, not subscribed
00170 
00171     // remove subscriber
00172     vec.erase(k);
00173 }
00174 
00175 void Blackboard::registerClient(BlackboardAccess *bbClient)
00176 {
00177     Enter_Method("registerClient(this)");
00178 
00179     // check if already subscribed
00180     SubscriberVector& vec = registeredClients;
00181     if (std::find(vec.begin(), vec.end(), bbClient)!=vec.end())
00182         return; // ok, already subscribed
00183 
00184     // add subscriber
00185     vec.push_back(bbClient);
00186 }
00187 
00188 void Blackboard::removeClient(BlackboardAccess *bbClient)
00189 {
00190     Enter_Method("removeClient(this)");
00191 
00192     // check if subscribed
00193     SubscriberVector& vec = registeredClients;
00194     SubscriberVector::iterator k = std::find(vec.begin(), vec.end(), bbClient);
00195     if (k==vec.end())
00196         return; // ok, not subscribed
00197 
00198     // remove subscriber
00199     vec.erase(k);
00200 }
00201 
00202 void Blackboard::getBlackboardContent(BlackboardAccess *bbClient)
00203 {
00204     Enter_Method("getBlackboardContent(this)");
00205 
00206     for (ContentsMap::iterator i=contents.begin(); i!=contents.end(); ++i)
00207         bbClient->blackboardItemPublished((*i).second);
00208 }
00209 
00210 //----
00211 
00212 Blackboard *BlackboardAccess::getBlackboard()
00213 {
00214     if (!bb)
00215     {
00216         bb = ModuleAccess<Blackboard>("blackboard").get();
00217     }
00218     return bb;
00219 }
00220 
00221