next up previous contents index
Next: 7 Mobility Modules Up: A Mobility Framework for Previous: 5 Physical Layer Modules   Contents   Index


6 Using the Blackboard

When you evaluate the performance of a protocol, you need information on internal state changes of your protocol, maybe even from protocols that you use. You could monitor these changes using e.g. vector files from within you protocol and remove these monitors once you are done. Another way is to use a blackboard. The state changes are published on it, and the monitors subscribe to these values. This allows other researchers to tap your protocol for performance evaluation, while imposing nearly no runtime penalty when the information is not needed.

Maybe even more importantly, the blackboard allows you to exchange information between layers, without passing pointers to the modules around. Some items might not only be interesting for the layer they are created/changed in. The physical layer for example (snrEval in the MF) can sense whether a channel is busy or not. If the MAC protocol is based on carrier sense it needs the information the physical layer has. The Blackboard is a module where the corresponding information can be published and then is accessible for any module interested in it.

The BasicModule provides everything necessary to interact with the blackboard. It is derived from ImNotifiable - a pure virtual base class that allows the blackboard to inform your module of changes - and contains a pointer named bb to the blackboard module.

6.1 Methods for the subscriber Subscribing to a parameter

If you want to subscribe to a parameter, the best place to do so is the initialize function in stage 0. Suppose for example that you want to subscribe to changes of an item of the class SomeBBItem. When this item is changed, you have to be able to interpret its contents - and the way you can be sure that you can interpret the data is to know its type (or class in C++). Such items can be signal strength indicators, active radio channels, routing table entries, reasons why packets where lost and so forth, we will talk more about it in a separate section.

void YourClass::initialize(int stage) {
    if (stage == 0){
        SomeBBItem item;
        catItem = bb->subscribe(this, &item, -1);
    else if(stage == 1) {

In case you want to subscribe to a parameter, i.e. you want to be informed each time the content/value of that parameter changes, you have to call the Blackboard function subscribe(). You have to include a pointer to your module, a pointer to an object of class SomeBBItem, and a scope. This function returns an integer that is unique for the class SomeBBItem. The section 6.2 shows how to use this parameter. The Blackboard uses the this pointer to notify the module of published changes. The object pointer & item helps the Blackboard to learn something about the changes that you are subscribing. The Blackboard uses it to establish the connection between the catItem and the &item. The last parameter of the function determines a scope, it needs a more detailed explanation. A change can be published by several modules within a host. Consider the RSSI and a host with more than one network card. Each of these cards will publish a separate RSSI - but it will be of the same class and can hence not be distinguished. However, the meaning of the RSSI is constrained to one card (its scope): it makes no sense for a MAC protocol of one card to take the RSSI of the other card into consideration. The solution is to include the scope into the publication and let the Blackboard do some filtering. In the example code the subscriber uses -1 as the scope - a wildcard that subscribes him to all changes published by any module. If you want to subscribe to some specific stuff, you must make sure that the scope (for network cards usually the module id of the card) under which the parameter is published, matches the subscribed scope. Un-subscribing from a parameter

Sometimes parameter changes make only sometimes sense. For example, the host may decide to go to sleep. In this case it may be reasonable to unsubscribe:
bb->unsubscribe(this, catItem);
Your module will not get notifications for this parameter anymore.

6.2 Getting informed

Let us assume that you subscribed to a value and there is a valid publisher. The publisher informs the Blackboard of a change, which in turn calls the receiveBBItem method that your class inherited from the abstract ImNotifiable base class.

void YourClass::receiveBBItem(int category, \ 
const BBItem *details, int scopeModuleId) {
  // in case you want to handle messages here
  // in case not you but your base class subscribed: 
  BaseClass::receiveBBItem(category, details, scopeModuleId);
  // react on the stuff that you subscribed
  if(category == catItem) {
      someBBItemPtr = 
           static_cast<const SomeBBItem *>(details);
      // do something 

The parameters of this function have already been explained in section 6.1. The first is the category, the integer that the subscribe function returned, the second is a pointer to an object of the class that you subscribed to and the third is the scope of this parameter. You should place the Enter_Method or Enter_Method_Silent macros at the beginning. This allows you to schedule or cancel messages, besides doing some animation. You should also inform the base class. This pattern is probably familiar from the initialize function. Now your base class will be informed about all changes it subscribed (and some of them are not interesting to YourClass) and the changes that YourClass subscribed. This has two implications: if you forget this line, the simulation may stop completely or behave strange. Secondly, YourClass must gracefully handle any items that it did not subscribe. To support you in that task, the item that you receive from the Blackboard is read-only.

In the next step, the published item is handled. It is easy to determine its type: just check (may be in a switch statement) the category and cast it to the right class. Since the association between a class and its category is fixed, a static cast is safe and fast. Now YourClass can interpret the content and do something about it.

6.3 Methods for the publisher Parameter

You can only publish objects, since in C++ classes carry the semantic meaning. An integer can be used for everything: counting missed lunches, counting stars, or packets. If you would subscribe to an integer - how can your class know how to interpret it? This is where classes help you:

class  MissedLunches : public BBItem {
    int counter;
    double getMissedLunches () const {
        return counter;
    void setMissedLunches(int c) {
        counter = c;
    void addMissedLunch() {

    MissedLunches(int c=0) : BBItem(), counter(c) {
       // constructor
    std::string info() const { // for inspection
        std::ostringstream ost;
        ost << " You missed  " << counter << " lunches.";
        return ost.str();
This associates the meaning ``missed lunch'' with an integer. At least, this is how most humans would interpret the name of the class. The class is derived directly from BBItem (which is derived from cPolymorphic), the base class for all items that can be published on the blackboard.

For advanced users: Of course it could also refine a class (say MissedMeals) and have a different parent class. The call to BBITEM_METAINFO(BBItem); helps the Blackboard to track the inheritance tree. If MissedLunches would have been derived from MissedMeals this should read BBITEM_METAINFO(MissedMeals);. This trick allows the Blackboard to deliver MissedLunches to all subscribers of MissedMeals.

After this you simply go ahead with a standard C++ class definition, and do what you like. The info function is optional, but helpful with debugging. Publishing

Ok, now that the parameter is defined, let us have a look how to publish it. First, some initialization is necessary. Let us assume that missedLunch is an object of class MissedLunches, and a member variable of YourPublisher.

void YourPublisher::initialize(int stage) {
    if(stage == 0) {
        // initialize it
        // get the category
        missedLunchCat = bb->getCategory(&missedLunch);
    else if(stage == 1) {
        bb->publishBBItem(missedLunchCat, \
          &missedLunch, parentModule()->id());

You should initialize missedLunches properly. The next step is to figure the category out, or put differently establish the connection between a category integer and a class. Now you are all set to publish it. We recommend that you publish your data in stage 1, this allows all subscribers to initialize the copies they might have. Publishing is a simple call to bb->publishBBItem . The first parameter is the category, the second a pointer to the published object that carries all the information that you want to publish, and the third is the scope. parentModule()->id() may not be useful as a scope in your case. There is no default or wildcard - you have to think about a reasonable and easy to understand scope.

Actually, we already covered how to publish a change when the simulation runs. Let us assume that YourPublisher tracks missed lunches somehow:

void YourPublisher::handleMissedLunch() {
       // update information 
       // publish it.
       bb->publishBBItem(missedLunchCat, \
          &missedLunch, parentModule()->id());

YourPublisher simply has to update the information, and call the publish function again. That's it.

next up previous contents index
Next: 7 Mobility Modules Up: A Mobility Framework for Previous: 5 Physical Layer Modules   Contents   Index
Daniel Willkomm 2007-01-12