I'm trying to write a message/event handler for my problem, but I'm having some problems getting it to behave like it should. It runs fine, but it doesn't clean up like it should.
The event handler keeps a queue of events, using
std::vector. Each event has three pieces of information: a numeric code representing the event, a string describing the event, and a numeric identifier to remember what part of the program added the event to the queue (which is what the clean up is based on).
A part of the program starts by resetting the event handler to the first event in the queue, and then repeatedly calling the handler to get the next message, until the handler signals the end of the messages by returning NULL.
As the handler goes through the messages in the queue, it cleans up by geting rid of messages that were added by the current part of the program.(Based on the assumption that every other part of the program has had a chance to read those messages.)
And herein lays the problem: the message handler only deletes every other message that should be deleted. My guess is that it has to do with
std::vector::iterator, or more specifically copying iterators.
Here is the source file where the error should be. I'm pretty sure that it's in the function
eventHandler::getEvent()
/*
* twiEventHandler.cpp
*/
#include <iostream>
#include "eventHandler.h"
eventHandler::eventHandler()
{
currentSource = 0;
}
eventHandler::~eventHandler()
{
// clear all variables
myEvents.clear();
}
void eventHandler::addEvent(int code, std::string msg, int source)
{
myEvents.push_back(event(code, msg, source)); // push the new message onto the back of the stack
}
void eventHandler::resetLoop(int id)
{
currentEvent = myEvents.begin();// go to the front of the stack
currentSource = id; // find out who's calling (used for cleanup);
}
event* eventHandler::getEvent()
{
// Current problem:
// if there is are events from the current source, only every other event will be removed
event* result = NULL;
bool finished = false; // flag that we found what we're looking for
// loop until we get the next valid message, or we hit the end of the messages
while (!finished)
{
// first see if we've reached the end of the message stack
if(currentEvent == myEvents.end())
{
// tell the loop to stop
finished = true;
}
else // still messages to go
{
//////////////////////////////////
// I'm pretty sure the problem is in the next few lines
//////////////////////////////////
// make a copy of the current position so that we don't loose our place if the current item gets deleted.
prevEvent = currentEvent;
currentEvent++;
// we see if we should get rid of this message
if(prevEvent->source == currentSource)
{
std::cout<<">>Removing message "<<prevEvent->code<<": "<<prevEvent->message<<" from module "<<prevEvent->source<<std::endl;
myEvents.erase(prevEvent);
}
else // if we don't get rid of it
{
// set the current message to return
result = &(*prevEvent);
// and tell the loop that we found what we're looking for
finished = true;
}
}
}
// go to the next message
return result;
}
void eventHandler::clear()
{
myEvents.clear(); // get rid of al messages
}
/*
* eventHandler.h
*/
#ifndef EVENT_HANDLER_H
#define EVENT_HANDLER_H
#include <string>
#include <map>
#include <vector>
// a container to hold all the parts of the message
typedef struct event
{
event() {}
event(int codeIn, std::string msgIn, int sourceIn)
{
code = codeIn;
message = msgIn;
source = sourceIn;
}
int code; // numerical code representing the message
std::string message; // human readable version of the message, mey have extra data
int source; // where the message came from, used for clean up
};
class eventHandler
{
public:
eventHandler();
~eventHandler();
void addEvent(int code, std::string msg, int source);
void resetLoop(int id); // go back the the first message, get what part of the program is calling (for cleanup)
event* getEvent(); // get the current message, then go to the next one
void clear(); // get rid of all messages
private:
std::vector<event>::iterator currentEvent;
std::vector<event>::iterator prevEvent;
int currentSource;
std::vector<event> myEvents;
};
#endif //EVENT_HANDLER_H
main.cpp
#include <iostream>
#include "eventHandler.h"
eventHandler myEvents;
void readEvents(int module)
{
std::cout<<"Running Module "<<module<<std::endl;
myEvents.resetLoop(module);
bool finished = false;
event* temp = NULL;
int eventCounter = 0;
while (!finished)
{
temp = myEvents.getEvent();
if(!temp)
{
finished = true;
}
else
{
eventCounter++;
std::cout<<"Event: "<<temp->code<<":"<<temp->message<<" (module "<<temp->source<<")"<<std::endl;
}
}
std::cout<<"Finished running module "<<module<<", "<<eventCounter<<" events"<<std::endl<<std::endl;
}
int main(int argc, char** argv)
{
readEvents(1);
myEvents.addEvent(1,"First event, first Module",1);
myEvents.addEvent(2,"Second Event, first Module", 1);
myEvents.addEvent(3, "Third Event, first Module", 1);
myEvents.addEvent(4, "Fourth Event, first Module", 1);
readEvents(3);
readEvents(1);
readEvents(3);
return 0;
}
Thanks for taking the time to look at this.