-
Notifications
You must be signed in to change notification settings - Fork 0
/
Event.h
104 lines (87 loc) · 2.23 KB
/
Event.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#pragma once
#include <list>
#include <memory>
template<typename F>
class Event;
template<typename R, typename... Args>
class Event<R(Args...)> {
private:
typedef Event<R(Args...)> ThisEvent;
public:
class Listener {
friend class ThisEvent;
private:
std::list<ThisEvent *> eventHosts;
void addEventHost(ThisEvent * theEvent) {
if (nullptr != theEvent && this->eventHosts.end() == std::find(this->eventHosts.begin(), this->eventHosts.end(), theEvent)) {
this->eventHosts.push_back(theEvent);
}
}
void removeEventHost(ThisEvent * theEvent) {
this->eventHosts.remove(theEvent);
}
virtual R raise(Args... args) = 0;
public:
~Listener() {
std::list<ThisEvent *> eventHosts = this->eventHosts;
for (ThisEvent * theEvent : eventHosts) {
theEvent->removeListener(*this);
}
}
};
template<typename T>
class MemberFunctionListener : public Listener {
private:
typedef R(T::*CallbackPtr)(Args...);
T * object = nullptr;
CallbackPtr callback = nullptr;
public:
MemberFunctionListener(T * object, CallbackPtr callback) {
this->object = object;
this->callback = callback;
}
virtual R raise(Args... args) {
if (nullptr != this->callback && nullptr != this->object) {
(this->object->*this->callback)(args...);
}
}
};
class FreeFunctionListener : public Listener {
private:
typedef R(*CallbackPtr)(Args...);
CallbackPtr callback;
public:
FreeFunctionListener(CallbackPtr callback) {
this->callback = callback;
}
virtual R raise(Args... args) {
if (nullptr != this->callback) {
(*this->callback)(args...);
}
}
};
private:
std::list<Listener *> listeners;
public:
~Event() {
std::list<Listener *> listeners = this->listeners;
for (Listener * listener : listeners) {
listener->removeEventHost(this);
}
}
void addListener(Listener & listener) {
if (this->listeners.end() == std::find(this->listeners.begin(), this->listeners.end(), &listener)) {
this->listeners.push_back(&listener);
listener.addEventHost(this);
}
}
void removeListener(Listener & listener) {
this->listeners.remove(&listener);
listener.removeEventHost(this);
}
R raise(Args... args) const {
for (Listener * listener : this->listeners) {
listener->raise(args...);
}
}
};