C++: event system implementation for a game engine

c++, events, game-engine

Solution

It is not strictly related to your question, but speaking about design, I'd avoid using a global notification system 'for everything' as I've seen bad consequences in the past. You'll just tend to use a heavy event system in places where one object would just call some method on another object.

Specialised templatatised systems work better, i.e. the systems that allow you to control objects' lifespan and that are designed to handle events of particular types and known parameters in them.

Any case, you'll find it hard to solve problems such as pending events wating for delivery to already-killed recipients.

Problem

I am planning an event driven game engine. The basic idea is that instead of having everything talking to everything, everything would talk to the event system, which would relay the messages to their recipients, without coupling the recipients to the notifiers or the other way around. - Objects register themselves to the event system. A notification ID and a pointer to a callback function are passed as parameters of each registration command. - Objects add notifications to the event system. The ID of the notification is passed as a parameter of each notification. The notifications are added to a queue holding all pending notifications. - Additionally, the event system supports scheduled notifications. The notification ID and the future time of execution are passed as parameters of each notification. The scheduled notifications are then stored in a data structure ("schedule") holding the scheduled notifications in order of the future time of execution. - An invoker object commands the event system to process all queued notifications. The event system fetches the notifications in order, and calls the callback function of each object that has registered itself with the same ID as the current notification. - An invoker object commands the event system to process one scheduled notification. The oldest notification is fetched from the schedule, and the callbacks of all objects registered with the same notification ID are called. . ``` class Registration { public: void callback(void){ callback_(); } void setCallback((*callback)(void)); void addToEventSystem(int ID, EventSystem &eventSystem); private: void (*callback_)(void); }; class EventSystem { public: void register(int ID, Registration* registration); void unRegister(int ID, Registration* registration); void addNotificationToQueue(int ID); void addNotificationToSchedule(int ID, int notificationTime); void processQueuedNotifications(void); void processNextScheduled(void); int getCurrentTime(void); private: //placeholder types <list> notificationQueue; <binaryheap> notificationSchedule; }; //------------Use:------------------ class ReceiverObject { public: void doStuff(void); void initialize(void){ keyPressRegistration.setCallback(doStuff); //multiple registrations with different ID:s to same eventsystem possible keyPressRegistration.addToEventSystem(1234,eventSystem); keyPressRegistration.addToEventSystem(42,eventSystem);}; private: Registration keyPressRegistration; }; int main() { ReceiverObject receiverObject; EventSystem eventSystem; receiverObject.initialize(); eventSystem.addNotificationToQueue(1234); eventSystem.processQueuedNotifications(); } ``` However I am not entirely satisfied with this solution, mostly because the system does not allow easy passing of parameters to recipients, and I am skeptical about callbacks to member functions, is it good design practice? What about the method/class/variable names I have come up with? Constructive criticism, guidance and alternative approaches to the problem are welcome.

Original source