NotificationBoard Class Reference

#include <NotificationBoard.h>

List of all members.


Detailed Description

Acts as a intermediary between module where state changes can occur and modules which are interested in learning about those changes; "Notification Broker".

Notification events are grouped into "categories." Examples of categories are: NF_HOSTPOSITION_UPDATED, NF_RADIOSTATE_CHANGED, NF_PP_TX_BEGIN, NF_PP_TX_END, NF_IPv4_ROUTE_ADDED, NF_BEACON_LOST NF_NODE_FAILURE, NF_NODE_RECOVERY, etc. Each category is identified by an integer (right now it's assigned in the source code via an enum, in the future we'll convert to dynamic category registration).

To trigger a notification, the client must obtain a pointer to the NotificationBoard of the given host or router (explained later), and call its fireChangeNotification() method. The notification will be delivered to all subscribed clients immediately, inside the fireChangeNotification() call.

Clients that wish to receive notifications should implement (subclass from) the INotifiable interface, obtain a pointer to the NotificationBoard, and subscribe to the categories they are interested in by calling the subscribe() method of the NotificationBoard. Notifications will be delivered to the receiveChangeNotification() method of the client (redefined from INotifiable).

In cases when the category itself (an int) does not carry enough information about the notification event, one can pass additional information in a data class. There is no restriction on what the data class may contain, except that it has to be subclassed from cPolymorphic, and of course producers and consumers of notifications should agree on its contents. If no extra info is needed, one can pass a NULL pointer in the fireChangeNotification() method.

A module which implements INotifiable looks like this:

 class Foo : public cSimpleModule, public INotifiable {
     ...
     virtual void receiveChangeNotification(int category, const cPolymorphic *details) {..}
     ...
 };
 

Obtaining a pointer to the NotificationBoard module of that host/router:

 NotificationBoard *nb; // this is best made a module class member
 nb = NotificationBoardAccess().get();  // best done in initialize()
 

See NED file for additional info.

See also:
INotifiable
Author:
Andras Varga

Public Types

typedef std::vector
< INotifiable * > 
NotifiableVector
typedef std::map< int,
NotifiableVector
ClientMap

Public Member Functions

Methods for consumers of change notifications


virtual void subscribe (INotifiable *client, int category)
virtual void unsubscribe (INotifiable *client, int category)
virtual bool hasSubscribers (int category)
Methods for producers of change notifications


virtual void fireChangeNotification (int category, const cPolymorphic *details=NULL)

Protected Member Functions

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

Protected Attributes

ClientMap clientMap

Friends

std::ostream & operator<< (std::ostream &, const NotifiableVector &)

Member Typedef Documentation


Member Function Documentation

void NotificationBoard::initialize (  )  [protected, virtual]

Initialize.

00051 {
00052     WATCH_MAP(clientMap);
00053 }

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

Does nothing.

00056 {
00057     error("NotificationBoard doesn't handle messages, it can be accessed via direct method calls");
00058 }

void NotificationBoard::subscribe ( INotifiable client,
int  category 
) [virtual]

Subscribe to changes of the given category

Referenced by RoutingTable6::initialize(), RoutingTable::initialize(), PPP::initialize(), NAMTraceWriter::initialize(), Mac80211::initialize(), LinkStateRouting::initialize(), LDP::initialize(), Ieee80211MgmtAP::initialize(), Ieee80211Mac::initialize(), Ieee80211AgentSTA::initialize(), CSMAMacLayer::initialize(), ChannelAccess::initialize(), EtherMACBase::initializeNotificationBoard(), and Ieee80211MgmtSTA::processScanCommand().

00062 {
00063     Enter_Method("subscribe(%s)", notificationCategoryName(category));
00064 
00065     // find or create entry for this category
00066     NotifiableVector& clients = clientMap[category];
00067 
00068     // add client if not already there
00069     if (std::find(clients.begin(), clients.end(), client) == clients.end())
00070         clients.push_back(client);
00071 
00072     fireChangeNotification(NF_SUBSCRIBERLIST_CHANGED, NULL);
00073 }

void NotificationBoard::unsubscribe ( INotifiable client,
int  category 
) [virtual]

Unsubscribe from changes of the given category

Referenced by Ieee80211MgmtSTA::scanNextChannel(), and PPP::~PPP().

00076 {
00077     Enter_Method("unsubscribe(%s)", notificationCategoryName(category));
00078 
00079     // find (or create) entry for this category
00080     NotifiableVector& clients = clientMap[category];
00081 
00082     // remove client if there
00083     NotifiableVector::iterator it = std::find(clients.begin(), clients.end(), client);
00084     if (it!=clients.end())
00085         clients.erase(it);
00086 
00087     fireChangeNotification(NF_SUBSCRIBERLIST_CHANGED, NULL);
00088 }

bool NotificationBoard::hasSubscribers ( int  category  )  [virtual]

Returns true if any client has subscribed to the given category. This, by using a local boolean 'hasSubscriber' flag, allows performance-critical clients to leave out calls to fireChangeNotification() if there's no one subscribed anyway. The flag should be refreshed on each NF_SUBSCRIBERLIST_CHANGED notification.

Referenced by PPP::updateHasSubcribers(), and EtherMAC2::updateHasSubcribers().

00091 {
00092     ClientMap::iterator it = clientMap.find(category);
00093     return it!=clientMap.end() && !it->second.empty();
00094 }

void NotificationBoard::fireChangeNotification ( int  category,
const cPolymorphic *  details = NULL 
) [virtual]

Tells NotificationBoard that a change of the given category has taken place. The optional details object may carry more specific information about the change (e.g. exact location, specific attribute that changed, old value, new value, etc).

Referenced by InterfaceTable::addInterface(), RoutingTable6::addOrUpdateOnLinkPrefix(), RoutingTable6::addOrUpdateOwnAdvPrefix(), RoutingTable6::addRoute(), RoutingTable::addRoute(), RSVP::announceLinkChange(), LDP::announceLinkChange(), Ieee80211MgmtSTA::beaconLost(), SnrEval::changeChannel(), AbstractRadio::changeChannel(), InterfaceTable::deleteInterface(), RoutingTable::deleteRoute(), EtherMACBase::fireChangeNotification(), Ieee80211MgmtSTA::handleAssociationResponseFrame(), EtherMAC2::handleEndTxPeriod(), SnrEval::handleLowerMsgEnd(), GilbertElliotSnr::handleLowerMsgEnd(), SnrEval::handleLowerMsgStart(), GilbertElliotSnr::handleLowerMsgStart(), PPP::handleMessage(), SnrEval::handleSelfMsg(), GilbertElliotSnr::handleSelfMsg(), SnrEval::handleUpperMsg(), SnrEval::initialize(), AbstractRadio::initialize(), InterfaceTable::interfaceChanged(), EtherMAC2::processMsgFromNetwork(), RoutingTable6::removeRoute(), AbstractRadio::setRadioState(), EtherMAC2::startFrameTransmission(), PPP::startTransmitting(), subscribe(), unsubscribe(), and BasicMobility::updatePosition().

00097 {
00098     Enter_Method("fireChangeNotification(%s, %s)", notificationCategoryName(category),
00099                  details?details->info().c_str() : "n/a");
00100 
00101     ClientMap::iterator it = clientMap.find(category);
00102     if (it==clientMap.end())
00103         return;
00104     NotifiableVector& clients = it->second;
00105     for (NotifiableVector::iterator j=clients.begin(); j!=clients.end(); j++)
00106         (*j)->receiveChangeNotification(category, details);
00107 }


Friends And Related Function Documentation

std::ostream& operator<< ( std::ostream &  os,
const NotifiableVector v 
) [friend]

00026 {
00027     os << v.size() << " client(s)";
00028     for (unsigned int i=0; i<v.size(); i++)
00029     {
00030         os << (i==0 ? ": " : ", ");
00031         if (dynamic_cast<cModule*>(v[i]))
00032         {
00033             cModule *mod = dynamic_cast<cModule*>(v[i]);
00034             os << "mod (" << mod->getClassName() << ")" << mod->getFullName() << " id=" << mod->getId();
00035         }
00036         else if (dynamic_cast<cPolymorphic*>(v[i]))
00037         {
00038             cPolymorphic *obj = dynamic_cast<cPolymorphic*>(v[i]);
00039             os << "a " << obj->getClassName();
00040         }
00041         else
00042         {
00043             os << "a " << opp_typename(typeid(v[i]));
00044         }
00045     }
00046     return os;
00047 }


Member Data Documentation


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

Generated on Fri Mar 20 18:51:20 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5