I3MUP1+-+Exercise+10

= Exercise 10 - The Message system =

Exercise 1 - The messageHandler
Constructoren bruges til at initialisere message queue størrelsen og stopId'en. getMsgQueue returnere den message queue en messageHandler har. Stop sender en besked ind på messageQueue'en med stopId. Funktionen handlMsg skal ikke implementeres da den er pure virtual. Funktionen run er arvet fra thread og vi har valgt at implementere den således at så længe der ikke running_ er sand, vil den stå og modtage funktioner og håndtere dem.
 * Implementation:**

code format="cpp" void MessageHandler::run {   running_ = true; unsigned long id;

while(running_) {       osapi::Message *msg; msg = mq_.receive(id); if(id==stopId_) {           running_ = false; }       handleMsg(msg,id); delete msg; } } code Vi brugte opgave 7.1. Som det første ændrede vi receiver thread til at arve fra vores messageHandler i stedet for fra thread. Da Messagehandler arver fra thread ændre det ikke på at vores receiver stadig er en thread. Så har vi slettet run funktionen fra reciever da den allerede er implementeret i messagehandleren. Sidst men ikke mindst ændre vi på receivers msgHandler så den følger den nedarvede messagehandlers virtuelle funktion.
 * Test:**

Exercise 2 - The MessageSystem
code format="cpp" void MessageSystem::subscribeMessage(const std::string& msgId, osapi::MsgQueue* mq,							unsigned long id) {	Subscriber newSubscriber(mq,id);
 * Implementation af MessageSystem:**

MapType::iterator it = map_.find(msgId);

if(it == map_.end) {		// First subscriber for this msgId VectorType vec; vec.push_back(newSubscriber);

mut_.lock; map_.insert(std::make_pair(msgId, vec)); mut_.unlock;

}	else {		VectorType& vec = it->second;

VectorType::iterator vit; vit = find(vec.begin,vec.end,newSubscriber);

if(vit == vec.end) {			mut_.lock; vec.push_back(newSubscriber); mut_.unlock; }	}

}

void MessageSystem::unSubscribeEvent(const std::string& msgId, osapi::MsgQueue* mq,							unsigned long id) {	Subscriber delSubscriber(mq,id); MapType::iterator it;

it = map_.find(msgId);

if(it == map_.end) {		// No subscriber for id	} else {		VectorType& vec = it->second;

VectorType::iterator vit; vit = find(vec.begin,vec.end, delSubscriber);

if(vit != vec.end) {			mut_.lock; vec.erase(vit); mut_.unlock; }	} }

code code format="cpp" template	void notify(const std::string& msgId, M* m)	{ MapType::iterator it;

it = map_.find(msgId);

if(it != map_.end) {			VectorType& vec = it->second;

VectorType::iterator vit; for(vit = vec.begin; vit != vec.end; ++vit) {				vit->send( new M(*m)); }		}		delete m;	}; code

Når en sender kalder notify, bliver den nød til at klone en message, så i tilfælde af multible modtagere ikke bruger delete på en message før alle modtager har brugt den.!
 * Why a template function: **


 * Subscriber Implementation: **

code format="cpp" Subscriber::Subscriber(osapi::MsgQueue* mq, unsigned long id) {	mq_ = mq; id_ = id; }

void Subscriber::send(osapi::Message* msg) const {	mq_->send(id_,msg); }

bool Subscriber::operator==(const Subscriber& other) const {	if(this->id_ == other.id_) {		if(this->mq_ == other.mq_) return true; }

return false; } code

Problemet med singleton implementeringen i dette system er at det ikke er thread-safe. Hvis to tråde prøver at tilgå objektet samtidigt, kan det hænde at hver tråd opretter hver sin instans.
 * Singelton pitfalls:**

Exercise 3 - Resource Management
code format="cpp" SubscriberId::SubscriberId {

}

SubscriberId::SubscriberId(const std::string& msgId, osapi::MsgQueue* mq, unsigned long id) {	msgId_ = msgId; mq_ = mq; id_ = id;

subscribe(msgId,mq,id); }

void SubscriberId::subscribe(const std::string& msgId, osapi::MsgQueue* mq, unsigned long id) {	MessageSystem::getInstance.subscribeMessage(msgId,mq,id); }

void SubscriberId::unSubscribe {	MessageSystem::getInstance.unSubscribeEvent(msgId_,mq_,id_); }

SubscriberId::~SubscriberId {	unSubscribe; } code