Listing 5
// test application for messaging system #include "Messaging.h" #include <iostream> #include <string> using namespace std; // some listener interface struct MartianAlertListener { virtual void martianLanded(const string &where) = 0; }; // some other listener interface struct NuclearPSListener { virtual void itIsHot(int temp) = 0; virtual void itIsTooLate() = 0; }; // a commong functionality of the normal person and // the technician in the nuclear power station class Person { public: Person(const string &name) : name_(name) {} string getName() const { return name_; } private: string name_; }; // a class representing the normal person // normal person is interested in the MartianAlert events class NormalPerson : public Person, public MartianAlertListener { public: NormalPerson(const string &name) : Person(name) {} // here, the Person receives the notification virtual void martianLanded(const string &where) { cout << getName() << ": martian landed " << where << endl; } }; // a context structure for MartianAlert events, // holding the info considering the landing place struct MartianContext { string where_; }; // the helper typedef typedef Messaging<MartianAlertListener, MartianContext> MartianAlertSource; // another class, representing a technician in // the nuclear power station // the technician is interested in // the events related to his job class Technician : public Person, public NuclearPSListener { public: Technician(const string &name) : Person(name) {} void itIsHot(int temp) { cout << getName() << ": there is " << temp << " degrees in the reactor" << endl; } void itIsTooLate() { cout << getName() << ": BANG!" << endl; } }; // a context structure for events in the power station, // holding info considering: // 1. what has happened // 2. what is the temperature in the reactor struct NuclearPSContext { enum eWhat {it_is_hot, it_is_too_late} whathappened_; int temp_; }; // the helper typedef typedef Messaging<NuclearPSListener, NuclearPSContext> NuclearPSSource; // the ultimate source of events // note multiple inheritance // (one for each listener type) class EventSource : public MartianAlertSource, public NuclearPSSource { public: // inherited from MartianAlertSource void dispatchEvent(MartianAlertListener *p, const MartianContext &context) { // just call the listener p->martianLanded(context.where_); } // inherited from NuclearPSSource void dispatchEvent(NuclearPSListener *p, const NuclearPSContext &context) { // we have a choice and parameters with some details if (context.whathappened_ == NuclearPSContext::it_is_hot) p->itIsHot(context.temp_); else p->itIsTooLate(); } // play a little with events void go() { // send a martian alert MartianContext ctx1; ctx1.where_ = "in the garden"; // note: if this class inherits from // only one event source base, // the operator:: is not needed MartianAlertSource::raiseEvent(ctx1); // send a temperature report NuclearPSContext ctx2; ctx2.whathappened_ = NuclearPSContext::it_is_hot; ctx2.temp_ = 5000; NuclearPSSource::raiseEvent(ctx2); // send a "too late" event notification NuclearPSContext ctx3; ctx3.whathappened_ = NuclearPSContext::it_is_too_late; NuclearPSSource::raiseEvent(ctx3); } }; int main() { // these are object which will receive // event notifications: NormalPerson john("John"); NormalPerson jenny("Jenny"); NormalPerson mike("Mike"); Technician tech1("technician 1"); Technician tech2("technician 2"); // this is a source of events EventSource source; // register objects as listeners in an event source // note: if an event source inherits from only one // event source base, the :: selectors are not needed source.MartianAlertSource::addListener(&john); source.MartianAlertSource::addListener(&jenny); source.MartianAlertSource::addListener(&mike); source.NuclearPSSource::addListener(&tech1); source.NuclearPSSource::addListener(&tech2); // play source.go(); return 0; }