Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Blackboard Class Reference

#include <Blackboard.h>

List of all members.


Detailed Description

The Blackboard works as entity to enable inter-layer/inter-process communication.

NOTE: BLACKBOARD IS NO LONGER USED BY THE INET FRAMEWORK -- SUCCESSOR IS NotificationBoard.

Blackboard makes it possible for several modules (representing e.g. protocol layers) to share information, in a publish-subscribe fashion. Participating modules or classes have to implement the BlackboardAccess interface (=have this abstract class as base class).

Anyone can publish data items on the blackboard. In order to allow for some type safety via dynamic_cast, items have to be subclassed from cPolymorphic.

Every item is published with a unique string label. The Blackboard makes no assumption about the format of the label, but it's generally a good idea to make it structured, e.g. with a dotted format ("nic1.linkstatus"). The label can be used by subscribers to identify an item ("I want to subscribe to nic1.linkstatus"). There are other ways to subscribe too, not only by label, e.g. one can browse through all Blackboard items, examine each (its label, C++ class, actual contents etc.) and decide individually whether to subscribe to it or not.

Labels are only used when publishing or subscribing to items. After that, items can be referred to using BBItemRefs. (BBItemRefs are sort of "handles" to blackboard items; think of file handles (fd's) or FILE* variables in Unix and C programming, or window handles (HWND) in the Windows API.) BBItemRefs allow very efficient (constant-time) access to Blackboard items.

Clients may browse blackboard contents and subscribe to items. After subscription, clients will receive notifications via BlackboardAccess callbacks whenever the subscribed item changes. Clients may also subscribe to get notified whenever items are published to or withdrawn from the blackboard.

Notifications are done with callback-like mechanism. Participating modules or classes have to subclass from the abstract base class BlackboardAccess and implement its methods (in Java, one would say clients should implement the BlackboardAccess interface.) This usually means multiple inheritance, but without the problems of multiple inheritance (Multiple inheritance is sometimes considered "evil", but never if used to do "mixins" as here.)

Some examples for usage. The first one, Foo demonstrates subscribe-by-name, the second one, Bar shows subscribe-when-published, and the third one, Zak does subscribe-by-browse.

 // subscribe-by-name
 class Foo : public cSimpleModule, public BlackboardAccess
 {
   protected:
     BBItemRef ref;
     ...
 };

 void Foo::initialize(int stage)
 {
     // to avoid a subscribe-BEFORE-publish a two stage
     // initialization should be used and all publish calls should
     // go into the first stage (stage 0) whereas you should subscribe
     // in the second stage (stage 1)
     if(stage==0)
     {
         ...
     }
     else if(stage==1)
     {
         ref = blackboard()->subscribe(this,"routingTable");
         ...
     }
 }

 void Foo::blackboardItemChanged(BBItemRef item)
 {
     if (item==ref)
     {
         RoutingTable *rt = check_and_cast<RoutingTable *>(ref->data());
         ...
     }
     else ...
 }

 // subscribe-when-published
 class Bar : public cSimpleModule, public BlackboardAccess
 {
    ...
 };

 void Bar::initialize(int stage)
 {
     if(stage==0)
     {
         blackboard()->registerClient(this);
         // make sure we get what's already on the blackboard
         blackboard()->getBlackboardContent(this);
     }
 }

 void Bar::blackboardItemPublished(BBItemRef item)
 {
     // if label begins with "nic." and it's a NetworkInterfaceData, subscribe
     if (!strncmp(item->label(),"nic.",4) &&
         dynamic_cast<NetworkInterfaceData *>(item->data()))
     {
         // new network interface appeared, subscribe to it and do whatever
         // other actions are necessary
         blackboard()->subscribe(this, item);
         ...
     }
 }

 // subscribe-by-browse
 class Zak : public cSimpleModule, public BlackboardAccess
 {
    ...
 };

 void Zak::letsCheckWhatIsOnTheBlackboard()
 {
     // subscribe to all NetworkInterfaceData
     Blackboard *bb = blackboard();
     for (Blackboard::iterator i=bb->begin(); i!=bb->end(); ++i)
         if (dynamic_cast<NetworkInterfaceData *>((*i)->data()))
             bb->subscribe(this, *i);
 }
 

Author:
Andras Varga


Public Types

typedef std::vector< BlackboardAccess * > SubscriberVector
typedef BBItemBBItemRef

Public Member Functions

 Blackboard ()
virtual ~Blackboard ()
Methods for publishers
BBItemRef publish (const char *label, cPolymorphic *item)
void withdraw (BBItemRef bbItem)
void changed (BBItemRef bbItem, cPolymorphic *item=NULL)
Methods for subscribers
BBItemRef subscribe (BlackboardAccess *bbClient, const char *label)
BBItemRef find (const char *label)
BBItemRef subscribe (BlackboardAccess *bbClient, BBItemRef bbItem)
void unsubscribe (BlackboardAccess *bbClient, BBItemRef bbItem)
void registerClient (BlackboardAccess *bbClient)
void removeClient (BlackboardAccess *bbClient)
void getBlackboardContent (BlackboardAccess *bbClient)
iterator begin ()
iterator end ()

Protected Types

typedef std::map< std::string,
BBItem * > 
ContentsMap

Protected Member Functions

virtual void initialize ()
virtual void handleMessage (cMessage *msg)

Protected Attributes

bool coreDebug
 Set debugging for the basic module.
class Iterator
ContentsMap contents
SubscriberVector registeredClients

Classes

class  BBItem
class  iterator


Member Typedef Documentation

typedef BBItem* Blackboard::BBItemRef
 

"Handle" to blackboard items. To get the data or the label, write bbref->data() and bbref->label(), respectively. BBItemRefs become stale when the item gets withdrawn (unpublished) from the blackboard.

typedef std::map<std::string, BBItem*> Blackboard::ContentsMap [protected]
 

typedef std::vector<BlackboardAccess *> Blackboard::SubscriberVector
 


Constructor & Destructor Documentation

Blackboard::Blackboard  ) 
 

00037 {
00038 }

Blackboard::~Blackboard  )  [virtual]
 

00041 {
00042     while (!contents.empty())
00043     {
00044         ContentsMap::iterator i = contents.begin();
00045         delete (*i).second;
00046         contents.erase(i);
00047     }
00048 }


Member Function Documentation

iterator Blackboard::begin  )  [inline]
 

As with standard C++ classes.

00312 {return iterator(contents.begin());}

void Blackboard::changed BBItemRef  bbItem,
cPolymorphic *  item = NULL
 

Tell BB that an item has changed (typically called by publisher). When item pointer is omitted, it is assumed that the item object was updated "in place" (as opposed to being replaced by another object).

00110 {
00111   coreEV <<"enter changed; item: "<<bbItem->label()<<" changed -> notify subscribers\n";
00112 
00113   Enter_Method("changed(\"%s\", %s *ptr)", bbItem->label(), item->className());
00114 
00115     // update data pointer
00116     if (item)
00117         bbItem->_item = item;
00118     // notify subscribers
00119     SubscriberVector& vec = bbItem->subscribers;
00120     for (SubscriberVector::iterator i=vec.begin(); i!=vec.end(); ++i){
00121         (*i)->blackboardItemChanged(bbItem);
00122     }
00123 }

iterator Blackboard::end  )  [inline]
 

As with standard C++ classes.

00317 {return iterator(contents.end());}

BBItemRef Blackboard::find const char *  label  ) 
 

Find item with given label on the BB

00141 {
00142     ContentsMap::iterator k = contents.find(std::string(label));
00143     return k==contents.end() ? NULL : (*k).second;
00144 }

void Blackboard::getBlackboardContent BlackboardAccess bbClient  ) 
 

Utility function: the client gets immediate notification with all items currently on clipboard (as if they were added just now). This may simplify initialization code in a subscribe-when-published style client.

00204 {
00205     Enter_Method("getBlackboardContent(this)");
00206 
00207     for (ContentsMap::iterator i=contents.begin(); i!=contents.end(); ++i)
00208         bbClient->blackboardItemPublished((*i).second);
00209 }

void Blackboard::handleMessage cMessage *  msg  )  [protected, virtual]
 

Does nothing.

00060 {
00061     error("Blackboard doesn't handle messages, it can be accessed via direct method calls");
00062 }

void Blackboard::initialize  )  [protected, virtual]
 

Initialize BB.

00051 {
00052   if(hasPar("coreDebug"))
00053     coreDebug = par("coreDebug").boolValue();
00054   else
00055     coreDebug = false;
00056     WATCH_PTRMAP(contents);
00057 }

BBItemRef Blackboard::publish const char *  label,
cPolymorphic *  item
 

Publish new item on the BB, with the given label.

00065 {
00066     Enter_Method("publish(\"%s\", %s *ptr)", label, item->className());
00067 
00068     // check uniqueness of label
00069     ContentsMap::iterator k = contents.find(std::string(label));
00070     if (k!=contents.end())
00071         error("publish(): blackboard already contains an item with label `%s'", label);
00072 
00073     // add to BB contents
00074     BBItem *bbitem = new BBItem();
00075     bbitem->_item = item;
00076     bbitem->_label = label;
00077     contents[bbitem->_label] = bbitem;
00078 
00079     coreEV <<"publish "<<label<<" on bb\n";
00080     coreEV <<"bbItem->label: "<<bbitem->label()<<endl;
00081     // notify
00082     SubscriberVector& vec = registeredClients;
00083     for (SubscriberVector::iterator i=vec.begin(); i!=vec.end(); ++i){
00084         (*i)->blackboardItemPublished(bbitem);
00085     }
00086     return bbitem;
00087 }

void Blackboard::registerClient BlackboardAccess bbClient  ) 
 

Generally subscribe to notifications about items being published to/withdrawn from BB.

00177 {
00178     Enter_Method("registerClient(this)");
00179 
00180     // check if already subscribed
00181     SubscriberVector& vec = registeredClients;
00182     if (std::find(vec.begin(), vec.end(), bbClient)!=vec.end())
00183         return; // ok, already subscribed
00184 
00185     // add subscriber
00186     vec.push_back(bbClient);
00187 }

void Blackboard::removeClient BlackboardAccess bbClient  ) 
 

Cancel subscription initiated by registerClient().

00190 {
00191     Enter_Method("removeClient(this)");
00192 
00193     // check if subscribed
00194     SubscriberVector& vec = registeredClients;
00195     SubscriberVector::iterator k = std::find(vec.begin(), vec.end(), bbClient);
00196     if (k==vec.end())
00197         return; // ok, not subscribed
00198 
00199     // remove subscriber
00200     vec.erase(k);
00201 }

BBItemRef Blackboard::subscribe BlackboardAccess bbClient,
BBItemRef  bbItem
 

Subscribe to a BB item identified by item reference

00147 {
00148     Enter_Method("subscribe(this,\"%s\")", bbItem->label());
00149 
00150     // check if already subscribed
00151     SubscriberVector& vec = bbItem->subscribers;
00152     if (std::find(vec.begin(), vec.end(), bbClient)!=vec.end())
00153         return bbItem; // already subscribed
00154 
00155     // add subscriber
00156     vec.push_back(bbClient);
00157 
00158     coreEV <<"sucessfully subscribed for item: "<<bbItem->label()<<endl;
00159     return bbItem;
00160 }

BBItemRef Blackboard::subscribe BlackboardAccess bbClient,
const char *  label
 

Subscribe to a BB item identified by a label

00126 {
00127     Enter_Method("subscribe(this,\"%s\")", label);
00128 
00129     // look up item by label
00130     BBItemRef item = find(label);
00131     if (!item)
00132        error("subscribe(): item labelled `%s' not on blackboard", label);
00133 
00134     // subscribe
00135     coreEV <<"subscribe for "<<label<<" on bb\n";
00136     subscribe(bbClient, item);
00137     return item;
00138 }

void Blackboard::unsubscribe BlackboardAccess bbClient,
BBItemRef  bbItem
 

Unsubcribe module from change notifications

00163 {
00164     Enter_Method("unsubscribe(this,\"%s\")", bbItem->label());
00165 
00166     // check if already subscribed
00167     SubscriberVector& vec = bbItem->subscribers;
00168     SubscriberVector::iterator k = std::find(vec.begin(), vec.end(), bbClient);
00169     if (k==vec.end())
00170         return; // ok, not subscribed
00171 
00172     // remove subscriber
00173     vec.erase(k);
00174 }

void Blackboard::withdraw BBItemRef  bbItem  ) 
 

Withdraw (unpublish) item from the BB (typically called by publisher).

00090 {
00091     Enter_Method("withdraw(\"%s\")", bbItem->label());
00092 
00093     // find on BB
00094     ContentsMap::iterator k = contents.find(bbItem->_label);
00095     if (k==contents.end())
00096       error("withdraw(): item labelled `%s' is not on clipboard (BBItemRef stale?)", bbItem->_label.c_str());
00097 
00098     // notify subscribers
00099     SubscriberVector& vec = bbItem->subscribers;
00100     for (SubscriberVector::iterator i=vec.begin(); i!=vec.end(); ++i)
00101         (*i)->blackboardItemWithdrawn(bbItem);
00102 
00103     // remove
00104     contents.erase(k);
00105     bbItem->_item = NULL; // may make bogus code crash sooner
00106     delete bbItem;
00107 }


Member Data Documentation

ContentsMap Blackboard::contents [protected]
 

bool Blackboard::coreDebug [protected]
 

Set debugging for the basic module.

class friend class Blackboard::Iterator [protected]
 

SubscriberVector Blackboard::registeredClients [protected]
 


The documentation for this class was generated from the following files:
Generated on Sat Apr 1 20:52:21 2006 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.1