Panda3D
Loading...
Searching...
No Matches
eventHandler.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file eventHandler.cxx
10 * @author drose
11 * @date 1999-02-08
12 */
13
14#include "eventHandler.h"
15#include "eventQueue.h"
16#include "config_event.h"
17
18using std::string;
19
20TypeHandle EventHandler::_type_handle;
21
22EventHandler *EventHandler::_global_event_handler = nullptr;
23
24
25/**
26 *
27 */
28EventHandler::
29EventHandler(EventQueue *ev_queue) : _queue(*ev_queue) {
30}
31
32/**
33 * Returns a pending future that will be marked as done when the event is next
34 * fired.
35 */
37get_future(const string &event_name) {
38 Futures::iterator fi;
39 fi = _futures.find(event_name);
40
41 // If we already have a future, but someone cancelled it, we need to create
42 // a new future instead.
43 if (fi != _futures.end() && !fi->second->cancelled()) {
44 return fi->second;
45 } else {
46 AsyncFuture *fut = new AsyncFuture;
47 _futures[event_name] = fut;
48 return fut;
49 }
50}
51
52/**
53 * The main processing loop of the EventHandler. This function must be called
54 * periodically to service events. Walks through each pending event and calls
55 * its assigned hooks.
56 */
59 while (!_queue.is_queue_empty()) {
60 dispatch_event(_queue.dequeue_event());
61 }
62}
63
64/**
65 * Calls the hooks assigned to the indicated single event.
66 */
68dispatch_event(const Event *event) {
69 nassertv(event != nullptr);
70
71 // Is the event name defined in the hook table? It will be if anyone has
72 // ever assigned a hook to this particular event name.
73 Hooks::const_iterator hi;
74 hi = _hooks.find(event->get_name());
75
76 if (hi != _hooks.end()) {
77 // Yes, it is! Now walk through all the functions assigned to that event
78 // name.
79 Functions copy_functions = (*hi).second;
80
81 Functions::const_iterator fi;
82 for (fi = copy_functions.begin(); fi != copy_functions.end(); ++fi) {
83 if (event_cat.is_spam()) {
84 event_cat->spam()
85 << "calling callback 0x" << (void*)(*fi)
86 << " for event '" << event->get_name() << "'"
87 << std::endl;
88 }
89 (*fi)(event);
90 }
91 }
92
93 // now for callback hooks
94 CallbackHooks::const_iterator chi;
95 chi = _cbhooks.find(event->get_name());
96
97 if (chi != _cbhooks.end()) {
98 // found one
99 CallbackFunctions copy_functions = (*chi).second;
100
101 CallbackFunctions::const_iterator cfi;
102 for (cfi = copy_functions.begin(); cfi != copy_functions.end(); ++cfi) {
103 ((*cfi).first)(event, (*cfi).second);
104 }
105 }
106
107 // Finally, check for futures that need to be triggered.
108 Futures::iterator fi;
109 fi = _futures.find(event->get_name());
110
111 if (fi != _futures.end()) {
112 AsyncFuture *fut = (*fi).second;
113 if (!fut->done()) {
114 fut->set_result((TypedReferenceCount *)event);
115 }
116 _futures.erase(fi);
117 }
118}
119
120
121/**
122 *
123 */
124void EventHandler::
125write(std::ostream &out) const {
126 Hooks::const_iterator hi;
127 hi = _hooks.begin();
128
129 CallbackHooks::const_iterator chi;
130 chi = _cbhooks.begin();
131
132 while (hi != _hooks.end() && chi != _cbhooks.end()) {
133 if ((*hi).first < (*chi).first) {
134 write_hook(out, *hi);
135 ++hi;
136 } else if ((*chi).first < (*hi).first) {
137 write_cbhook(out, *chi);
138 ++chi;
139 } else {
140 write_hook(out, *hi);
141 write_cbhook(out, *chi);
142 ++hi;
143 ++chi;
144 }
145 }
146
147 while (hi != _hooks.end()) {
148 write_hook(out, *hi);
149 ++hi;
150 }
151
152 while (chi != _cbhooks.end()) {
153 write_cbhook(out, *chi);
154 ++chi;
155 }
156}
157
158
159
160/**
161 * Adds the indicated function to the list of those that will be called when
162 * the named event is thrown. Returns true if the function was successfully
163 * added, false if it was already defined on the indicated event name.
164 */
166add_hook(const string &event_name, EventFunction *function) {
167 if (event_cat.is_debug()) {
168 event_cat.debug()
169 << "adding hook for event '" << event_name
170 << "' with function 0x" << (void*)function << std::endl;
171 }
172 assert(!event_name.empty());
173 assert(function);
174 return _hooks[event_name].insert(function).second;
175}
176
177
178/**
179 * Adds the indicated function to the list of those that will be called when
180 * the named event is thrown. Returns true if the function was successfully
181 * added, false if it was already defined on the indicated event name. This
182 * version records an untyped pointer to user callback data.
183 */
185add_hook(const string &event_name, EventCallbackFunction *function,
186 void *data) {
187 assert(!event_name.empty());
188 assert(function);
189 return _cbhooks[event_name].insert(CallbackFunction(function, data)).second;
190}
191
192/**
193 * Returns true if there is any hook added on the indicated event name, false
194 * otherwise.
195 */
197has_hook(const string &event_name) const {
198 assert(!event_name.empty());
199 Hooks::const_iterator hi;
200 hi = _hooks.find(event_name);
201 if (hi != _hooks.end()) {
202 if (!(*hi).second.empty()) {
203 return true;
204 }
205 }
206
207 CallbackHooks::const_iterator chi;
208 chi = _cbhooks.find(event_name);
209 if (chi != _cbhooks.end()) {
210 if (!(*chi).second.empty()) {
211 return true;
212 }
213 }
214
215 return false;
216}
217
218
219/**
220 * Returns true if there is the hook added on the indicated event name and
221 * function pointer, false otherwise.
222 */
224has_hook(const string &event_name, EventFunction *function) const {
225 assert(!event_name.empty());
226 Hooks::const_iterator hi;
227 hi = _hooks.find(event_name);
228 if (hi != _hooks.end()) {
229 const Functions& functions = (*hi).second;
230 if (functions.find(function) != functions.end()) {
231 return true;
232 }
233 }
234
235 return false;
236}
237
238
239/**
240 * Returns true if there is the hook added on the indicated event name,
241 * function pointer and callback data, false otherwise.
242 */
244has_hook(const string &event_name, EventCallbackFunction *function, void *data) const {
245 assert(!event_name.empty());
246 CallbackHooks::const_iterator chi;
247 chi = _cbhooks.find(event_name);
248 if (chi != _cbhooks.end()) {
249 const CallbackFunctions& cbfunctions = (*chi).second;
250 if (cbfunctions.find(CallbackFunction(function, data)) != cbfunctions.end()) {
251 return true;
252 }
253 }
254
255 return false;
256}
257
258
259/**
260 * Removes the indicated function from the named event hook. Returns true if
261 * the hook was removed, false if it wasn't there in the first place.
262 */
264remove_hook(const string &event_name, EventFunction *function) {
265 assert(!event_name.empty());
266 assert(function);
267 return _hooks[event_name].erase(function) != 0;
268}
269
270
271/**
272 * Removes the indicated function from the named event hook. Returns true if
273 * the hook was removed, false if it wasn't there in the first place. This
274 * version takes an untyped pointer to user callback data.
275 */
277remove_hook(const string &event_name, EventCallbackFunction *function,
278 void *data) {
279 assert(!event_name.empty());
280 assert(function);
281 return _cbhooks[event_name].erase(CallbackFunction(function, data)) != 0;
282}
283
284/**
285 * Removes all functions from the named event hook. Returns true if any
286 * functions were removed, false if there were no functions added to the hook.
287 */
289remove_hooks(const string &event_name) {
290 assert(!event_name.empty());
291 bool any_removed = false;
292
293 Hooks::iterator hi = _hooks.find(event_name);
294 if (hi != _hooks.end()) {
295 if (!(*hi).second.empty()) {
296 any_removed = true;
297 }
298 _hooks.erase(hi);
299 }
300
301 CallbackHooks::iterator chi = _cbhooks.find(event_name);
302 if (chi != _cbhooks.end()) {
303 if (!(*chi).second.empty()) {
304 any_removed = true;
305 }
306 _cbhooks.erase(chi);
307 }
308
309 return any_removed;
310}
311
312/**
313 * Removes all CallbackFunction hooks that have the indicated pointer as the
314 * associated data pointer.
315 */
317remove_hooks_with(void *data) {
318 bool any_removed = false;
319
320 CallbackHooks::iterator chi;
321 for (chi = _cbhooks.begin(); chi != _cbhooks.end(); ++chi) {
322 CallbackFunctions &funcs = (*chi).second;
323 CallbackFunctions::iterator cfi;
324
325 CallbackFunctions new_funcs;
326 for (cfi = funcs.begin(); cfi != funcs.end(); ++cfi) {
327 if ((*cfi).second == data) {
328 any_removed = true;
329 } else {
330 new_funcs.insert(*cfi);
331 }
332 }
333 funcs.swap(new_funcs);
334 }
335
336 return any_removed;
337}
338
339
340/**
341 * Removes all hooks assigned to all events.
342 */
345 _hooks.clear();
346 _cbhooks.clear();
347}
348
349/**
350 *
351 */
352void EventHandler::
353make_global_event_handler() {
355 _global_event_handler = new EventHandler(EventQueue::get_global_event_queue());
356}
357
358
359/**
360 *
361 */
362void EventHandler::
363write_hook(std::ostream &out, const EventHandler::Hooks::value_type &hook) const {
364 if (!hook.second.empty()) {
365 out << hook.first << " has " << hook.second.size() << " functions.\n";
366 }
367}
368
369/**
370 *
371 */
372void EventHandler::
373write_cbhook(std::ostream &out, const EventHandler::CallbackHooks::value_type &hook) const {
374 if (!hook.second.empty()) {
375 out << hook.first << " has " << hook.second.size() << " callback functions.\n";
376 }
377}
This class represents a thread-safe handle to a promised future result of an asynchronous operation,...
Definition asyncFuture.h:61
void set_result(std::nullptr_t)
Sets this future's result.
Definition asyncFuture.I:92
bool done() const
Returns true if the future is done or has been cancelled.
Definition asyncFuture.I:29
A class to monitor events from the C++ side of things.
void process_events()
The main processing loop of the EventHandler.
bool remove_hooks_with(void *data)
Removes all CallbackFunction hooks that have the indicated pointer as the associated data pointer.
virtual void dispatch_event(const Event *event)
Calls the hooks assigned to the indicated single event.
bool remove_hooks(const std::string &event_name)
Removes all functions from the named event hook.
void remove_all_hooks()
Removes all hooks assigned to all events.
AsyncFuture * get_future(const std::string &event_name)
Returns a pending future that will be marked as done when the event is next fired.
bool remove_hook(const std::string &event_name, EventFunction *function)
Removes the indicated function from the named event hook.
bool has_hook(const std::string &event_name) const
Returns true if there is any hook added on the indicated event name, false otherwise.
bool add_hook(const std::string &event_name, EventFunction *function)
Adds the indicated function to the list of those that will be called when the named event is thrown.
A queue of pending events.
Definition eventQueue.h:29
static EventQueue * get_global_event_queue()
Returns a pointer to the one global EventQueue object.
Definition eventQueue.I:19
A named event, possibly with parameters.
Definition event.h:33
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
A base class for things which need to inherit from both TypedObject and from ReferenceCount.
This is our own Panda specialization on the default STL set.
Definition pset.h:49
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void init_memory_hook()
Any code that might need to use PANDA_MALLOC or PANDA_FREE, or any methods of the global memory_hook ...
Definition dtoolbase.cxx:38
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.