|
INET Framework for OMNeT++/OMNEST
|
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