#include <NotificationBoard.h>
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_LAYER2_HANDOVER_OCCURRED, NF_IPv4_ROUTINGTABLE_CHANGED, 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, 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.
Public Types | |
typedef std::vector< INotifiable * > | NotifiableVector |
typedef std::map< int, NotifiableVector > | ClientMap |
Public Member Functions | |
Methods for consumers of change notifications | |
void | subscribe (INotifiable *client, int category) |
void | unsubscribe (INotifiable *client, int category) |
Methods for producers of change notifications | |
void | fireChangeNotification (int category, 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 &) |
|
|
|
|
|
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). 00088 { 00089 Enter_Method("fireChangeNotification(%s, %s)", notificationCategoryName(category), 00090 details?details->info().c_str() : "n/a"); 00091 00092 ClientMap::iterator it = clientMap.find(category); 00093 if (it==clientMap.end()) 00094 return; 00095 NotifiableVector& clients = it->second; 00096 for (NotifiableVector::iterator j=clients.begin(); j!=clients.end(); j++) 00097 (*j)->receiveChangeNotification(category, details); 00098 }
|
|
Does nothing. 00057 {
00058 error("NotificationBoard doesn't handle messages, it can be accessed via direct method calls");
00059 }
|
|
Initialize. 00052 { 00053 WATCH_MAP(clientMap); 00054 }
|
|
Subscribe to changes of the given category 00063 { 00064 Enter_Method("subscribe(%s)", notificationCategoryName(category)); 00065 00066 // find or create entry for this category 00067 NotifiableVector& clients = clientMap[category]; 00068 00069 // add client if not already there 00070 if (std::find(clients.begin(), clients.end(), client) == clients.end()) 00071 clients.push_back(client); 00072 }
|
|
Unsubscribe from changes of the given category 00075 { 00076 Enter_Method("unsubscribe(%s)", notificationCategoryName(category)); 00077 00078 // find (or create) entry for this category 00079 NotifiableVector& clients = clientMap[category]; 00080 00081 // remove client if there 00082 NotifiableVector::iterator it = std::find(clients.begin(), clients.end(), client); 00083 if (it!=clients.end()) 00084 clients.erase(it); 00085 }
|
|
00027 { 00028 os << v.size() << " client(s)"; 00029 for (unsigned int i=0; i<v.size(); i++) 00030 { 00031 os << (i==0 ? ": " : ", "); 00032 if (dynamic_cast<cModule*>(v[i])) 00033 { 00034 cModule *mod = dynamic_cast<cModule*>(v[i]); 00035 os << "mod (" << mod->className() << ")" << mod->fullName() << " id=" << mod->id(); 00036 } 00037 else if (dynamic_cast<cPolymorphic*>(v[i])) 00038 { 00039 cPolymorphic *obj = dynamic_cast<cPolymorphic*>(v[i]); 00040 os << "a " << obj->className(); 00041 } 00042 else 00043 { 00044 os << "a " << opp_typename(typeid(v[i])); 00045 } 00046 } 00047 return os; 00048 }
|
|
|