INET Framework for OMNeT++/OMNEST
Blackboard Class Reference

#include <Blackboard.h>

List of all members.

Classes

class  BBItem
class  iterator

Public Types

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

Public Member Functions

 Blackboard ()
virtual ~Blackboard ()
Methods for publishers
virtual BBItemRef publish (const char *label, cPolymorphic *item)
virtual void withdraw (BBItemRef bbItem)
virtual void changed (BBItemRef bbItem, cPolymorphic *item=NULL)
Methods for subscribers
virtual BBItemRef subscribe (BlackboardAccess *bbClient, const char *label)
virtual BBItemRef find (const char *label)
virtual BBItemRef subscribe (BlackboardAccess *bbClient, BBItemRef bbItem)
virtual void unsubscribe (BlackboardAccess *bbClient, BBItemRef bbItem)
virtual void registerClient (BlackboardAccess *bbClient)
virtual void removeClient (BlackboardAccess *bbClient)
virtual 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.
ContentsMap contents
SubscriberVector registeredClients

Friends

class Iterator

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 = getBlackboard()->subscribe(this,"routingTable");
         ...
     }
 }
 void Foo::blackboardItemChanged(BBItemRef item)
 {
     if (item==ref)
     {
         IRoutingTable *rt = check_and_cast<IRoutingTable *>(ref->getData());
         ...
     }
     else ...
 }
 // subscribe-when-published
 class Bar : public cSimpleModule, public BlackboardAccess
 {
    ...
 };
 void Bar::initialize(int stage)
 {
     if(stage==0)
     {
         getBlackboard()->registerClient(this);
         // make sure we get what's already on the blackboard
         getBlackboard()->getBlackboardContent(this);
     }
 }
 void Bar::blackboardItemPublished(BBItemRef item)
 {
     // if label begins with "nic." and it's a NetworkInterfaceData, subscribe
     if (!strncmp(item->getLabel(),"nic.",4) &&
         dynamic_cast<NetworkInterfaceData *>(item->getData()))
     {
         // new network interface appeared, subscribe to it and do whatever
         // other actions are necessary
         getBlackboard()->subscribe(this, item);
         ...
     }
 }
 // subscribe-by-browse
 class Zak : public cSimpleModule, public BlackboardAccess
 {
    ...
 };
 void Zak::letsCheckWhatIsOnTheBlackboard()
 {
     // subscribe to all NetworkInterfaceData
     Blackboard *bb = getBlackboard();
     for (Blackboard::iterator i=bb->begin(); i!=bb->end(); ++i)
         if (dynamic_cast<NetworkInterfaceData *>((*i)->getData()))
             bb->subscribe(this, *i);
 }
 
Author:
Andras Varga

Member Typedef Documentation

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

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

Constructor & Destructor Documentation

Blackboard::Blackboard ( )
{
}
Blackboard::~Blackboard ( ) [virtual]
{
    while (!contents.empty())
    {
        ContentsMap::iterator i = contents.begin();
        delete (*i).second;
        contents.erase(i);
    }
}

Member Function Documentation

iterator Blackboard::begin ( ) [inline]

As with standard C++ classes.

{return iterator(contents.begin());}
void Blackboard::changed ( BBItemRef  bbItem,
cPolymorphic *  item = NULL 
) [virtual]

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).

{
  coreEV <<"enter changed; item: "<<bbItem->getLabel()<<" changed -> notify subscribers\n";

  Enter_Method("changed(\"%s\", %s *ptr)", bbItem->getLabel(), item->getClassName());

    // update data pointer
    if (item)
        bbItem->_item = item;
    // notify subscribers
    SubscriberVector& vec = bbItem->subscribers;
    for (SubscriberVector::iterator i=vec.begin(); i!=vec.end(); ++i){
        (*i)->blackboardItemChanged(bbItem);
    }
}
iterator Blackboard::end ( ) [inline]

As with standard C++ classes.

{return iterator(contents.end());}
BBItemRef Blackboard::find ( const char *  label) [virtual]

Find item with given label on the BB

Referenced by removeClient(), subscribe(), and unsubscribe().

{
    ContentsMap::iterator k = contents.find(std::string(label));
    return k==contents.end() ? NULL : (*k).second;
}
void Blackboard::getBlackboardContent ( BlackboardAccess bbClient) [virtual]

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.

{
    Enter_Method("getBlackboardContent(this)");

    for (ContentsMap::iterator i=contents.begin(); i!=contents.end(); ++i)
        bbClient->blackboardItemPublished((*i).second);
}
void Blackboard::handleMessage ( cMessage *  msg) [protected, virtual]

Does nothing.

{
    error("Blackboard doesn't handle messages, it can be accessed via direct method calls");
}
void Blackboard::initialize ( ) [protected, virtual]

Initialize BB.

{
  if(hasPar("coreDebug"))
    coreDebug = par("coreDebug").boolValue();
  else
    coreDebug = false;
    WATCH_PTRMAP(contents);
}
BBItemRef Blackboard::publish ( const char *  label,
cPolymorphic *  item 
) [virtual]

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

{
    Enter_Method("publish(\"%s\", %s *ptr)", label, item->getClassName());

    // check uniqueness of label
    ContentsMap::iterator k = contents.find(std::string(label));
    if (k!=contents.end())
        error("publish(): blackboard already contains an item with label `%s'", label);

    // add to BB contents
    BBItem *bbitem = new BBItem();
    bbitem->_item = item;
    bbitem->_label = label;
    contents[bbitem->_label] = bbitem;

    coreEV <<"publish "<<label<<" on bb\n";
    coreEV <<"bbItem->label: "<<bbitem->getLabel()<<endl;
    // notify
    SubscriberVector& vec = registeredClients;
    for (SubscriberVector::iterator i=vec.begin(); i!=vec.end(); ++i){
        (*i)->blackboardItemPublished(bbitem);
    }
    return bbitem;
}
void Blackboard::registerClient ( BlackboardAccess bbClient) [virtual]

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

{
    Enter_Method("registerClient(this)");

    // check if already subscribed
    SubscriberVector& vec = registeredClients;
    if (std::find(vec.begin(), vec.end(), bbClient)!=vec.end())
        return; // ok, already subscribed

    // add subscriber
    vec.push_back(bbClient);
}
void Blackboard::removeClient ( BlackboardAccess bbClient) [virtual]

Cancel subscription initiated by registerClient().

{
    Enter_Method("removeClient(this)");

    // check if subscribed
    SubscriberVector& vec = registeredClients;
    SubscriberVector::iterator k = std::find(vec.begin(), vec.end(), bbClient);
    if (k==vec.end())
        return; // ok, not subscribed

    // remove subscriber
    vec.erase(k);
}
BBItemRef Blackboard::subscribe ( BlackboardAccess bbClient,
BBItemRef  bbItem 
) [virtual]

Subscribe to a BB item identified by item reference

{
    Enter_Method("subscribe(this,\"%s\")", bbItem->getLabel());

    // check if already subscribed
    SubscriberVector& vec = bbItem->subscribers;
    if (std::find(vec.begin(), vec.end(), bbClient)!=vec.end())
        return bbItem; // already subscribed

    // add subscriber
    vec.push_back(bbClient);

    coreEV <<"sucessfully subscribed for item: "<<bbItem->getLabel()<<endl;
    return bbItem;
}
BBItemRef Blackboard::subscribe ( BlackboardAccess bbClient,
const char *  label 
) [virtual]

Subscribe to a BB item identified by a label

{
    Enter_Method("subscribe(this,\"%s\")", label);

    // look up item by label
    BBItemRef item = find(label);
    if (!item)
       error("subscribe(): item labelled `%s' not on blackboard", label);

    // subscribe
    coreEV <<"subscribe for "<<label<<" on bb\n";
    subscribe(bbClient, item);
    return item;
}
void Blackboard::unsubscribe ( BlackboardAccess bbClient,
BBItemRef  bbItem 
) [virtual]

Unsubcribe module from change notifications

{
    Enter_Method("unsubscribe(this,\"%s\")", bbItem->getLabel());

    // check if already subscribed
    SubscriberVector& vec = bbItem->subscribers;
    SubscriberVector::iterator k = std::find(vec.begin(), vec.end(), bbClient);
    if (k==vec.end())
        return; // ok, not subscribed

    // remove subscriber
    vec.erase(k);
}
void Blackboard::withdraw ( BBItemRef  bbItem) [virtual]

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

{
    Enter_Method("withdraw(\"%s\")", bbItem->getLabel());

    // find on BB
    ContentsMap::iterator k = contents.find(bbItem->_label);
    if (k==contents.end())
      error("withdraw(): item labelled `%s' is not on clipboard (BBItemRef stale?)", bbItem->_label.c_str());

    // notify subscribers
    SubscriberVector& vec = bbItem->subscribers;
    for (SubscriberVector::iterator i=vec.begin(); i!=vec.end(); ++i)
        (*i)->blackboardItemWithdrawn(bbItem);

    // remove
    contents.erase(k);
    bbItem->_item = NULL; // may make bogus code crash sooner
    delete bbItem;
}

Friends And Related Function Documentation

friend class Iterator [friend]

Member Data Documentation

bool Blackboard::coreDebug [protected]

Set debugging for the basic module.

Referenced by initialize().


The documentation for this class was generated from the following files: