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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
#include "UnityPrefix.h"
#include "EventManager.h"
#include "Runtime/Utilities/InitializeAndCleanup.h"
////@TODO: Assert on recursive calls...
EventManager* EventManager::s_Instance = NULL;
EventManager& GetEventManager ()
{
return *EventManager::s_Instance;
}
void EventManager::StaticInitialize()
{
s_Instance = UNITY_NEW(EventManager,kMemManager);
}
void EventManager::StaticDestroy()
{
UNITY_DELETE(s_Instance, kMemManager);
}
static RegisterRuntimeInitializeAndCleanup s_EventManagerCallbacks(EventManager::StaticInitialize, EventManager::StaticDestroy);
EventManager::EventManager ()
: m_EventPool (false, "EventManager", sizeof(EventEntry), 1024 * 4)
#if DEBUGMODE
, m_InvokingEventList(NULL)
, m_InvokingEventActiveNode(NULL)
#endif
{
}
EventManager::EventIndex EventManager::AddEvent (EventCallback* callback, void* userData, EventIndex previousIndex)
{
if (previousIndex == NULL)
{
EventIndex event = (EventIndex)m_EventPool.Allocate();
event->userData = userData;
event->callback = callback;
event->next = NULL;
return event;
}
else
{
EventIndex event = (EventIndex)m_EventPool.Allocate();
event->callback = callback;
event->userData = userData;
event->next = previousIndex;
return event;
}
}
/// Removes all events with the event index.
void EventManager::RemoveEvent (EventIndex index)
{
#if DEBUGMODE
// We can not delete the event which we are currently invoking
Assert (m_InvokingEventList != index);
#endif
while (index != NULL)
{
EventIndex next = index->next;
m_EventPool.Deallocate(index);
index = next;
}
}
bool EventManager::HasEvent (const EventIndex index, EventCallback* callback, const void* userData)
{
EventIndex curIndex = index;
while (curIndex != NULL)
{
if (curIndex->callback == callback && curIndex->userData == userData)
return true;
curIndex = curIndex->next;
}
return false;
}
/// Removes an event with a specific callback & userData
/// Returns the new event or null if no events in that index exist anymore.
EventManager::EventIndex EventManager::RemoveEvent (EventIndex index, EventCallback* callback, void* userData)
{
EventIndex previousIndex = NULL;
EventIndex curEvent = index;
while (curEvent != NULL)
{
if (curEvent->callback == callback && curEvent->userData == userData)
{
// While invoking we are allowed to remove the event being invoked itself but no other events on the same chain.
#if DEBUGMODE
Assert (m_InvokingEventList != index || m_InvokingEventActiveNode == curEvent);
#endif
EventIndex nextEvent = curEvent->next;
m_EventPool.Deallocate(curEvent);
if (previousIndex)
previousIndex->next = nextEvent;
if (index == curEvent)
return nextEvent;
else
return index;
}
previousIndex = curEvent;
curEvent = curEvent->next;
}
return index;
}
void EventManager::InvokeEvent (EventIndex index, void* senderUserData, int eventType)
{
#if DEBUGMODE
GetEventManager().m_InvokingEventList = index;
#endif
while (index != NULL)
{
EventIndex next = index->next;
#if DEBUGMODE
GetEventManager().m_InvokingEventActiveNode = index;
#endif
index->callback(index->userData, senderUserData, eventType);
index = next;
}
#if DEBUGMODE
GetEventManager().m_InvokingEventList = NULL;
GetEventManager().m_InvokingEventActiveNode = NULL;
#endif
}
#if ENABLE_UNIT_TESTS
#include "External/UnitTest++/src/UnitTest++.h"
struct LoggingCounter
{
int counter;
};
void LoggingCallback (void* userData, void* sender, int type)
{
LoggingCounter* logging = (LoggingCounter*)userData;
logging->counter++;
}
SUITE (EventsManagerTest)
{
TEST (EventsManager_EventsSimple)
{
EventManager manager;
LoggingCounter counter1;
counter1.counter = 0;
EventManager::EventIndex index = manager.AddEvent (LoggingCallback, &counter1, NULL);
manager.InvokeEvent(index, NULL, 0);
CHECK_EQUAL(1, counter1.counter);
}
// Test chaining (But not duplicating)
TEST (EventsManager_EventsChaining)
{
EventManager manager;
LoggingCounter counter1;
counter1.counter = 0;
LoggingCounter counter2;
counter2.counter = 0;
LoggingCounter counter3;
counter3.counter = 0;
EventManager::EventIndex index;
// Add chained event (add one duplicate which should not be added or invoked)
index = manager.AddEvent (LoggingCallback, &counter1, NULL);
index = manager.AddEvent (LoggingCallback, &counter2, index);
index = manager.AddEvent (LoggingCallback, &counter3, index);
manager.InvokeEvent(index, NULL, 0);
CHECK_EQUAL(1, counter1.counter);
CHECK_EQUAL(1, counter2.counter);
CHECK_EQUAL(1, counter3.counter);
// Remove 1 chained event
index = manager.RemoveEvent (index, LoggingCallback, &counter2);
counter1.counter = 0;
counter2.counter = 0;
counter3.counter = 0;
manager.InvokeEvent(index, NULL, 0);
CHECK_EQUAL(1, counter1.counter);
CHECK_EQUAL(0, counter2.counter);
CHECK_EQUAL(1, counter3.counter);
}
}
#endif
|