Event Manager Issues

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Event Manager Issues

      Not sure if this is the right place to ask about this, but it seemed the best option.

      I'm trying to write my own event manager for a game i'm working on, but it's acting very strange. It works great when I've got just two events being listened to, but it freaks out when I add a third.

      The Manager:

      Source Code

      1. void EventManager::RegisterEventType(HashedString str)
      2. {
      3. for(unsigned int a = 0; a < RegisteredEvents.size(); a++)
      4. {
      5. if(str == RegisteredEvents[a])
      6. {
      7. printf("Event Type %s Already Registered!\n", str.getStr());
      8. return;
      9. }
      10. }
      11. RegisteredEvents.push_back(str);
      12. }
      13. bool EventManager::CheckEventRegistered(HashedString str)
      14. {
      15. for(unsigned int a = 0; a < RegisteredEvents.size(); a++)
      16. {
      17. if(str == RegisteredEvents[a])
      18. return true;
      19. }
      20. printf("Warning: Event %s Not Registered!\n", str.getStr());
      21. return false;
      22. }
      23. void EventManager::Tick()
      24. {
      25. while ( Queue.size() > 0 )
      26. {
      27. // Get an event from the queue
      28. IEvent* nEvent = Queue.back();
      29. Queue.pop_back();
      30. // Get the list of listeners attached to that event
      31. EventListenerMap::Iterator i = ListenerMap.find(nEvent->getType());
      32. // If there aren't any listeners for this event, start over
      33. if(i.atEnd())
      34. continue;
      35. ListenerList list = (*i).getValue();
      36. // Iterate through the listeners and hand them the event.
      37. for(ListenerList::Iterator it = list.begin(); it!=list.end(); it++)
      38. {
      39. if((*it)->HandleEvent( nEvent ))
      40. break;
      41. }
      42. delete nEvent;
      43. }
      44. }
      45. void EventManager::QueueEvent(IEvent* evnt)
      46. {
      47. // Add an event to the queue
      48. curQueue->push_front(evnt);
      49. }
      50. void EventManager::AddListener(HashedString evnt, IListener *listener)
      51. {
      52. if(!CheckEventRegistered(evnt))
      53. return;
      54. // Find the event type
      55. EventListenerMap::Iterator it = ListenerMap.find(evnt);
      56. // If we don't have a map entry for this event type already, create a new one.
      57. if(it.atEnd())
      58. {
      59. ListenerList list;
      60. list.push_back(listener);
      61. ListenerMap.insert(evnt, list);
      62. return;
      63. }
      64. // Attach a listener to an event
      65. (*it).getValue().push_back(listener);
      66. }
      Display All


      The Listeners:
      (Logic)

      Source Code

      1. // Listen for anything that the logic needs to worry about.
      2. manager.AddListener(QuitEvent::type, this);
      3. manager.AddListener(DetachSceneEvent::type, this);

      (HumanView)

      Source Code

      1. manager.AddListener(ButtonDownEvent::type, view);


      The two 'this' pointers are to the logic class, which is derived from IListener. The 'view' pointer is the HumanView, which is also derived from IListener.

      When the code is run like that, it sends the detach event to the HumanView, not the Logic. When I comment the DetachSceneEvent line it works fine. When I comment the QuitEvent line, it sends the ButtonDownEvent to the Logic instead.

      I have no clue what is going on. If anyone has any tips they would be greatly appreciated.

      [Edit]
      So if I add a bunch of random characters to the base strings of the Quit and DetachScene events, it works. I don't know why. I've checked to make sure that the register/check registered routines work and they do, so I don't know what's happening.

      The post was edited 5 times, last by Nethara ().

    • I'm not sure about your particular issue, but I see an unrelated error. Inside of your Tick() function, if there are no listeners for a given event type, that event doesn't get deleted, so there will be a memory leak. You might want to look in to using shared_ptr as Mike recommended in the book. It is included in Visual Studio 2010's STL's, so you don't even need to include boost to get it.

      Regarding your issue, unless I'm missing some registration code, I fail to see how any of the events are firing. Your first line in AddListener checks to see if an event type is registered, and returns if it isn't. However I'm not seeing anywhere where that registration is called?
    • I see a number of issues that will probably cause you headaches but I'm not sure exactly which one could be causing this issue. Can you include the class definition you're using as well?

      -Rez
    • Originally posted by rickvanprim
      I'm not sure about your particular issue, but I see an unrelated error. Inside of your Tick() function, if there are no listeners for a given event type, that event doesn't get deleted, so there will be a memory leak. You might want to look in to using shared_ptr as Mike recommended in the book. It is included in Visual Studio 2010's STL's, so you don't even need to include boost to get it.

      Regarding your issue, unless I'm missing some registration code, I fail to see how any of the events are firing. Your first line in AddListener checks to see if an event type is registered, and returns if it isn't. However I'm not seeing anywhere where that registration is called?


      Thanks, I completely missed that particular leak. I do have a memory checker running so I probably would have gotten it eventually once I forgot to set a listener, but nice catch. I really should go back and rework what I have for shared pointers.

      I added the registration code in an edit and forgot to add in the lines where I actually did the registration. It's there in the source.

      Source Code

      1. manager.RegisterEventType(QuitEvent::type);
      2. manager.RegisterEventType(ButtonDownEvent::type);
      3. manager.RegisterEventType(DetachSceneEvent::type);


      P.S. What headaches were you referring to? I was trying to write this on my own without referring to the book, and so far the few tests that I've done have worked quite well. Any help would be greatly appreciated.

      The post was edited 2 times, last by Nethara ().

    • Found something that probably has something to do with this.

      I threw in this line right after checking i.AtEnd()

      Source Code

      1. printf("Event %s fired, found listener key %s\n", nEvent->getType().getStr(), i->getKey().getStr());


      The output is "Event Button_Down_Event fired, found listener key Quit_Game_Event" when I click a button.

      How this happens I have no clue. Apparently my ListenerMap.find() call returned a value that had a different key than the input. Could it be an issue with using a HashedString as the key for a map?
    • I fixed it.

      It turns out that I was using a different version of map, which was included with the graphics engine that I'm working with. It seems to have some issues, but switching back to the STL versions made it work.

      Thanks for the help.

      P.S. Still somewhat curious about what headaches you were referring to.
    • RE: Event Manager Issues

      Eh, it was mostly just nit-picky stuff. Never mind the old man behind the curtain. ;)

      -Rez