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.
.
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.
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, ie 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.
I personally would have a interface class of EventHandler
, that you can register, which will have a virtual action
function (and perhaps a function for the event system to tell the class that it's being unregistered). This completely avoids callbacks, and the actual implementation of the EventHandler
will have the possibility of holding other data (or references to other data).
For the parameters issue - You can define base class ParamList whose derivates are templated:
class ParamList
{
const ID_Type& GetParamsType();
...
};
template <typename T>
class Params: public ParamList
{
...
}
now callbacks will be of type: void (*Callback)(ParamList&); for safety usage you can add to class Registration const ID_Type& GetExpectedParamsType(); and use it before calling the call back
sames go for notifications: void addNotificationToQueue(int ID, ParamList& param); void addNotificationToSchedule(int ID, ParamList& param,int notificationTime);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.