Øvelse+10+-+Message+system

Introduktion

Som forlængelse af vores MessageQueue system, ønsker vi at udvikle et system, hvor en central klasse "MessageSystem" holder styr på beskeder. Her kan andre klasser så abonnerer på beskeder. Optræder en given besked, skal MessageSystem så oplyse alle klasser der abonnerer på beskeden. Klassen messageHandler fungerer som en basisklasse der kan nedarves fra til alt der vil håndterer beskeder. Netop derfor at den handle funktion også virtual.

I forsimplet form ser systemet sådan ud:



Subscriber
Klassen fungerer som basisklasse for alle klasser, som alle andre klasse der ønsker at modtage beskeder kan nedarve fra.

Klassen har følgende interface: code format="cpp" class Subscriber { public: Subscriber(osapi::MsgQueue* mq, unsigned long id); void send(osapi::Message* msg) const; bool operator==(const Subscriber& other) const;

private: osapi::MsgQueue* mq_; unsigned long id_; }; code

MessageSystem
Hver enkelt besked defineres af en unik string kaldet msgId.

Klassen holder styr på abonnomenter, Fundementalt for klassen er et std::map, som bruger msgId som keys i. Til hver key ligger en stl vector, som inderholder de subscribers, som vil abonnere på den besked, der er på keyen.

Derfor indeholder klassen en funktion subscribe, som sætter en sybscriber ind i mappet, og en funktion unsubscribe, som fjerner en subscriber fra mappet.

Klassen laves singleton, det vil sige at constructoren er private, det er altså kun

Notify-funktionen
Funktion skal give besked til dem der abbonnere på en given besked. Den skal være en template funktion. Det skyldes at det er subscriberne der skal nedlægge beskeden, og da beskeden skal sendes ud til evt mange modtagere er det nødvendigt at de får en kopi. Da beskederne kan være af forskellige typer er det nødvendigt er vide hvordan der skal kopiers.

Fremgangsmetoden for funktionen er som følger:
 * Der kigges efter om der ligger noget i mappet på keyen "msgId"
 * Er det tilfældet løber man vectoren igennem.
 * For hver subscriber i vectoren oprettes en kopi af beskeden som sendes

Kode: code format="cpp" template   void notify(const std::string& msgId, M* m)    { MsgMap::iterator it = myMap.find(msgId); //leder efter msgId if(it != myMap.end) //hvis der ligger noget ved keyen {           SubscriberList& sl = it->second; //adgang til vectoren SubscriberList::iterator vIt; //iterator til vector for ( vIt = sl.begin; vIt != sl.end; ++vIt ) {               M* tempm = new M(*m); vIt->send(tempm); }

}   } code

subscriber-funktionen
Funktionen er implementeret som følger code format="cpp" void subscribeMessage(const std::string& msgId, osapi::MsgQueue* mq, unsigned long id) {       //opret et map, med string keys, //til hver key er der mappet en stl vector der indeholder subscribers af typen messagequeue Subscriber s(mq,id);

// Findes den i forvejen? MsgMap::iterator it = myMap.find(msgId); if (it != myMap.end) //hvis stl-vectoren ikke er tom {           //iterer gennem vectoren og kig efter s            SubscriberList& sl = it->second;

if (find(sl.begin, sl.end, s) == sl.end) {

sl.push_back(s); myMap[msgId] = sl; }

}

} code Funktionen starter med at lægge messagequeuen og id'et ind i en subscriber, så denne kan gemmes i vectoren, som indeholder objekter af typen subscriber.

Herefter oprettes en iterator it, som kigger mappet i gennem efter keyen "msgId", hvis den findes kigger man om der er en ikke-tom vector på pladsen. I denne vector lægges den nye subscriber ind. Der er nu subscribet på msgId'et.