Guide to the event system

An event system allows communication between unknown parties. By having a standard system a producer can signal events that interested parts may receive. The sender doesn't know who will receive events and the receiver doesn't need to know the concrete sender. The system is typically modeled by the observer pattern [GoF 293].

The event system in OpenEngine consists of a hierarchy of template classes.

The use of templates allows the event system to pass varying structures to varying receivers, all while still performing static type checking.

To use the event system one must make use of several components. We will explain each in turn while referring to the usage of events in the IKeyboard interface.

Event structure

Each event is represented as some data structure. This data structure is event specific and the following is a simple example hereof:

    #!cpp
    struct SomeEventArg {
      int x, y, z; // event data fields
    };

We use the post fix arg because the event structure is received as an argument to a event handler method as seen below.

The IKeyboard interface makes use of KeyboardEventArg.

Event handler

The usual usage of the system is to receive events. To do that some custom structure must serve as a handler. The handler must have a method that accepts a single argument corresponding to the type of the event structure. This structure is not restricted to being a handler and may be responsible for other things at the same time.

A simple example could be as follows:

    #!cpp
    class SomeEventHandler {

    public:

      void HandleSomeEvent(SomeEventArg event) {
        // do something on each received event
      }

      // ... other class functions ...

    };

Event list

For each event to be listened on a list must exist that allows handlers to register them selves.

The list is made with the Event template parametrized by the type of the event structure. The list will usually be a static field of some interface or it could be a global variable.

    #!cpp
    #include <EventSystem/Event.h>
    Event<SomeEventArg> someEvent;

The IKeyboard interface supplies two events. One for up and one for down.

Event listener

Finally we need to bind the handler to the event. To preserve typing we create a wrapper we call a Listener that couples the handler and the event argument. It is parametrized by the handler class, the event structure. The constructor takes a reference to the handler object and the address of the handler method.

    #!cpp
    // create an instance of the handler
    SomeEventHandler* handler = new SomeEventHandler();

    // create a wrapper
    Listener<SomeEventHandler, SomeEventArg> someListener
      = new Listener<SomeEventHandler, SomeEventArg>(*handler, &SomeEventHandler::HandleSomeEvent);
    
    // bind it to the event
    someEvent.Add(someListener);

Sending events

Now triggering an event is as simple as:

  #!cpp
  // create new event date
  SomeEventArg e;
  e.x = 1; e.y = 2; e.z = 3;

  // fire the event
  someEvent.Notify(e);

All handlers registered to the event will now have the body of their handler functions executed.