00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "CEventQueue.h"
00020 #include "CLog.h"
00021 #include "CSimpleEventQueueBuffer.h"
00022 #include "CStopwatch.h"
00023 #include "IEventJob.h"
00024 #include "CArch.h"
00025
00026
00027 static
00028 void
00029 interrupt(CArch::ESignal, void*)
00030 {
00031 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
00032 }
00033
00034
00035
00036
00037
00038
00039 CEventQueue::CEventQueue() :
00040 m_nextType(CEvent::kLast)
00041 {
00042 setInstance(this);
00043 m_mutex = ARCH->newMutex();
00044 ARCH->setSignalHandler(CArch::kINTERRUPT, &interrupt, NULL);
00045 ARCH->setSignalHandler(CArch::kTERMINATE, &interrupt, NULL);
00046 m_buffer = new CSimpleEventQueueBuffer;
00047 }
00048
00049 CEventQueue::~CEventQueue()
00050 {
00051 delete m_buffer;
00052 ARCH->setSignalHandler(CArch::kINTERRUPT, NULL, NULL);
00053 ARCH->setSignalHandler(CArch::kTERMINATE, NULL, NULL);
00054 ARCH->closeMutex(m_mutex);
00055 setInstance(NULL);
00056 }
00057
00058 void
00059 CEventQueue::loop()
00060 {
00061 CEvent event;
00062 getEvent(event);
00063 while (event.getType() != CEvent::kQuit) {
00064 dispatchEvent(event);
00065 CEvent::deleteData(event);
00066 getEvent(event);
00067 }
00068 }
00069
00070 CEvent::Type
00071 CEventQueue::registerType(const char* name)
00072 {
00073 CArchMutexLock lock(m_mutex);
00074 m_typeMap.insert(std::make_pair(m_nextType, name));
00075 m_nameMap.insert(std::make_pair(name, m_nextType));
00076 LOG((CLOG_DEBUG1 "registered event type %s as %d", name, m_nextType));
00077 return m_nextType++;
00078 }
00079
00080 CEvent::Type
00081 CEventQueue::registerTypeOnce(CEvent::Type& type, const char* name)
00082 {
00083 CArchMutexLock lock(m_mutex);
00084 if (type == CEvent::kUnknown) {
00085 m_typeMap.insert(std::make_pair(m_nextType, name));
00086 m_nameMap.insert(std::make_pair(name, m_nextType));
00087 LOG((CLOG_DEBUG1 "registered event type %s as %d", name, m_nextType));
00088 type = m_nextType++;
00089 }
00090 return type;
00091 }
00092
00093 const char*
00094 CEventQueue::getTypeName(CEvent::Type type)
00095 {
00096 switch (type) {
00097 case CEvent::kUnknown:
00098 return "nil";
00099
00100 case CEvent::kQuit:
00101 return "quit";
00102
00103 case CEvent::kSystem:
00104 return "system";
00105
00106 case CEvent::kTimer:
00107 return "timer";
00108
00109 default:
00110 CTypeMap::const_iterator i = m_typeMap.find(type);
00111 if (i == m_typeMap.end()) {
00112 return "<unknown>";
00113 }
00114 else {
00115 return i->second;
00116 }
00117 }
00118 }
00119
00120 void
00121 CEventQueue::adoptBuffer(IEventQueueBuffer* buffer)
00122 {
00123 CArchMutexLock lock(m_mutex);
00124
00125 LOG((CLOG_DEBUG "adopting new buffer"));
00126
00127 if (m_events.size() != 0) {
00128
00129
00130 LOG((CLOG_DEBUG "discarding %d event(s)", m_events.size()));
00131 }
00132
00133
00134 delete m_buffer;
00135 for (CEventTable::iterator i = m_events.begin(); i != m_events.end(); ++i) {
00136 CEvent::deleteData(i->second);
00137 }
00138 m_events.clear();
00139 m_oldEventIDs.clear();
00140
00141
00142 m_buffer = buffer;
00143 if (m_buffer == NULL) {
00144 m_buffer = new CSimpleEventQueueBuffer;
00145 }
00146 }
00147
00148 bool
00149 CEventQueue::getEvent(CEvent& event, double timeout)
00150 {
00151 CStopwatch timer(true);
00152 retry:
00153
00154 while (m_buffer->isEmpty()) {
00155
00156 if (hasTimerExpired(event)) {
00157 return true;
00158 }
00159
00160
00161 double timeLeft = timeout - timer.getTime();
00162 if (timeout >= 0.0 && timeLeft <= 0.0) {
00163 return false;
00164 }
00165
00166
00167
00168
00169 double timerTimeout = getNextTimerTimeout();
00170 if (timeout < 0.0 || (timerTimeout >= 0.0 && timerTimeout < timeLeft)) {
00171 timeLeft = timerTimeout;
00172 }
00173
00174
00175 m_buffer->waitForEvent(timeLeft);
00176 }
00177
00178
00179 UInt32 dataID;
00180 IEventQueueBuffer::Type type = m_buffer->getEvent(event, dataID);
00181 switch (type) {
00182 case IEventQueueBuffer::kNone:
00183 if (timeout < 0.0 || timeout <= timer.getTime()) {
00184
00185
00186
00187 goto retry;
00188 }
00189 return false;
00190
00191 case IEventQueueBuffer::kSystem:
00192 return true;
00193
00194 case IEventQueueBuffer::kUser:
00195 {
00196 CArchMutexLock lock(m_mutex);
00197 event = removeEvent(dataID);
00198 return true;
00199 }
00200
00201 default:
00202 assert(0 && "invalid event type");
00203 return false;
00204 }
00205 }
00206
00207 bool
00208 CEventQueue::dispatchEvent(const CEvent& event)
00209 {
00210 void* target = event.getTarget();
00211 IEventJob* job = getHandler(event.getType(), target);
00212 if (job == NULL) {
00213 job = getHandler(CEvent::kUnknown, target);
00214 }
00215 if (job != NULL) {
00216 job->run(event);
00217 return true;
00218 }
00219 return false;
00220 }
00221
00222 void
00223 CEventQueue::addEvent(const CEvent& event)
00224 {
00225
00226 switch (event.getType()) {
00227 case CEvent::kUnknown:
00228 case CEvent::kSystem:
00229 case CEvent::kTimer:
00230 return;
00231
00232 default:
00233 break;
00234 }
00235
00236 if ((event.getFlags() & CEvent::kDeliverImmediately) != 0) {
00237 dispatchEvent(event);
00238 CEvent::deleteData(event);
00239 }
00240 else {
00241 CArchMutexLock lock(m_mutex);
00242
00243
00244 UInt32 eventID = saveEvent(event);
00245
00246
00247 if (!m_buffer->addEvent(eventID)) {
00248
00249 removeEvent(eventID);
00250 CEvent::deleteData(event);
00251 }
00252 }
00253 }
00254
00255 CEventQueueTimer*
00256 CEventQueue::newTimer(double duration, void* target)
00257 {
00258 assert(duration > 0.0);
00259
00260 CEventQueueTimer* timer = m_buffer->newTimer(duration, false);
00261 if (target == NULL) {
00262 target = timer;
00263 }
00264 CArchMutexLock lock(m_mutex);
00265 m_timers.insert(timer);
00266
00267
00268
00269 m_timerQueue.push(CTimer(timer, duration,
00270 duration + m_time.getTime(), target, false));
00271 return timer;
00272 }
00273
00274 CEventQueueTimer*
00275 CEventQueue::newOneShotTimer(double duration, void* target)
00276 {
00277 assert(duration > 0.0);
00278
00279 CEventQueueTimer* timer = m_buffer->newTimer(duration, true);
00280 if (target == NULL) {
00281 target = timer;
00282 }
00283 CArchMutexLock lock(m_mutex);
00284 m_timers.insert(timer);
00285
00286
00287
00288 m_timerQueue.push(CTimer(timer, duration,
00289 duration + m_time.getTime(), target, true));
00290 return timer;
00291 }
00292
00293 void
00294 CEventQueue::deleteTimer(CEventQueueTimer* timer)
00295 {
00296 CArchMutexLock lock(m_mutex);
00297 for (CTimerQueue::iterator index = m_timerQueue.begin();
00298 index != m_timerQueue.end(); ++index) {
00299 if (index->getTimer() == timer) {
00300 m_timerQueue.erase(index);
00301 break;
00302 }
00303 }
00304 CTimers::iterator index = m_timers.find(timer);
00305 if (index != m_timers.end()) {
00306 m_timers.erase(index);
00307 }
00308 m_buffer->deleteTimer(timer);
00309 }
00310
00311 void
00312 CEventQueue::adoptHandler(CEvent::Type type, void* target, IEventJob* handler)
00313 {
00314 CArchMutexLock lock(m_mutex);
00315 IEventJob*& job = m_handlers[target][type];
00316 delete job;
00317 job = handler;
00318 }
00319
00320 void
00321 CEventQueue::removeHandler(CEvent::Type type, void* target)
00322 {
00323 IEventJob* handler = NULL;
00324 {
00325 CArchMutexLock lock(m_mutex);
00326 CHandlerTable::iterator index = m_handlers.find(target);
00327 if (index != m_handlers.end()) {
00328 CTypeHandlerTable& typeHandlers = index->second;
00329 CTypeHandlerTable::iterator index2 = typeHandlers.find(type);
00330 if (index2 != typeHandlers.end()) {
00331 handler = index2->second;
00332 typeHandlers.erase(index2);
00333 }
00334 }
00335 }
00336 delete handler;
00337 }
00338
00339 void
00340 CEventQueue::removeHandlers(void* target)
00341 {
00342 std::vector<IEventJob*> handlers;
00343 {
00344 CArchMutexLock lock(m_mutex);
00345 CHandlerTable::iterator index = m_handlers.find(target);
00346 if (index != m_handlers.end()) {
00347
00348 CTypeHandlerTable& typeHandlers = index->second;
00349 for (CTypeHandlerTable::iterator index2 = typeHandlers.begin();
00350 index2 != typeHandlers.end(); ++index2) {
00351 handlers.push_back(index2->second);
00352 }
00353 typeHandlers.clear();
00354 }
00355 }
00356
00357
00358 for (std::vector<IEventJob*>::iterator index = handlers.begin();
00359 index != handlers.end(); ++index) {
00360 delete *index;
00361 }
00362 }
00363
00364 bool
00365 CEventQueue::isEmpty() const
00366 {
00367 return (m_buffer->isEmpty() && getNextTimerTimeout() != 0.0);
00368 }
00369
00370 IEventJob*
00371 CEventQueue::getHandler(CEvent::Type type, void* target) const
00372 {
00373 CArchMutexLock lock(m_mutex);
00374 CHandlerTable::const_iterator index = m_handlers.find(target);
00375 if (index != m_handlers.end()) {
00376 const CTypeHandlerTable& typeHandlers = index->second;
00377 CTypeHandlerTable::const_iterator index2 = typeHandlers.find(type);
00378 if (index2 != typeHandlers.end()) {
00379 return index2->second;
00380 }
00381 }
00382 return NULL;
00383 }
00384
00385 UInt32
00386 CEventQueue::saveEvent(const CEvent& event)
00387 {
00388
00389 UInt32 id;
00390 if (!m_oldEventIDs.empty()) {
00391
00392 id = m_oldEventIDs.back();
00393 m_oldEventIDs.pop_back();
00394 }
00395 else {
00396
00397 id = static_cast<UInt32>(m_events.size());
00398 }
00399
00400
00401 m_events[id] = event;
00402 return id;
00403 }
00404
00405 CEvent
00406 CEventQueue::removeEvent(UInt32 eventID)
00407 {
00408
00409 CEventTable::iterator index = m_events.find(eventID);
00410 if (index == m_events.end()) {
00411 return CEvent();
00412 }
00413
00414
00415 CEvent event = index->second;
00416 m_events.erase(index);
00417
00418
00419 m_oldEventIDs.push_back(eventID);
00420
00421 return event;
00422 }
00423
00424 bool
00425 CEventQueue::hasTimerExpired(CEvent& event)
00426 {
00427
00428
00429
00430 if (m_timerQueue.empty()) {
00431 return false;
00432 }
00433
00434
00435 const double time = m_time.getTime();
00436 m_time.reset();
00437
00438
00439 for (CTimerQueue::iterator index = m_timerQueue.begin();
00440 index != m_timerQueue.end(); ++index) {
00441 (*index) -= time;
00442 }
00443
00444
00445 if (m_timerQueue.top() > 0.0) {
00446 return false;
00447 }
00448
00449
00450 CTimer timer = m_timerQueue.top();
00451 m_timerQueue.pop();
00452
00453
00454 timer.fillEvent(m_timerEvent);
00455 event = CEvent(CEvent::kTimer, timer.getTarget(), &m_timerEvent);
00456 timer.reset();
00457
00458
00459 if (!timer.isOneShot()) {
00460 m_timerQueue.push(timer);
00461 }
00462
00463 return true;
00464 }
00465
00466 double
00467 CEventQueue::getNextTimerTimeout() const
00468 {
00469
00470
00471
00472 if (m_timerQueue.empty()) {
00473 return -1.0;
00474 }
00475 if (m_timerQueue.top() <= 0.0) {
00476 return 0.0;
00477 }
00478 return m_timerQueue.top();
00479 }
00480
00481 CEvent::Type
00482 CEventQueue::getRegisteredType(const CString& name) const
00483 {
00484 CNameMap::const_iterator found = m_nameMap.find(name);
00485 if (found != m_nameMap.end())
00486 return found->second;
00487
00488 return CEvent::kUnknown;
00489 }
00490
00491
00492
00493
00494
00495
00496 CEventQueue::CTimer::CTimer(CEventQueueTimer* timer, double timeout,
00497 double initialTime, void* target, bool oneShot) :
00498 m_timer(timer),
00499 m_timeout(timeout),
00500 m_target(target),
00501 m_oneShot(oneShot),
00502 m_time(initialTime)
00503 {
00504 assert(m_timeout > 0.0);
00505 }
00506
00507 CEventQueue::CTimer::~CTimer()
00508 {
00509
00510 }
00511
00512 void
00513 CEventQueue::CTimer::reset()
00514 {
00515 m_time = m_timeout;
00516 }
00517
00518 CEventQueue::CTimer&
00519 CEventQueue::CTimer::operator-=(double dt)
00520 {
00521 m_time -= dt;
00522 return *this;
00523 }
00524
00525 CEventQueue::CTimer::operator double() const
00526 {
00527 return m_time;
00528 }
00529
00530 bool
00531 CEventQueue::CTimer::isOneShot() const
00532 {
00533 return m_oneShot;
00534 }
00535
00536 CEventQueueTimer*
00537 CEventQueue::CTimer::getTimer() const
00538 {
00539 return m_timer;
00540 }
00541
00542 void*
00543 CEventQueue::CTimer::getTarget() const
00544 {
00545 return m_target;
00546 }
00547
00548 void
00549 CEventQueue::CTimer::fillEvent(CTimerEvent& event) const
00550 {
00551 event.m_timer = m_timer;
00552 event.m_count = 0;
00553 if (m_time <= 0.0) {
00554 event.m_count = static_cast<UInt32>((m_timeout - m_time) / m_timeout);
00555 }
00556 }
00557
00558 bool
00559 CEventQueue::CTimer::operator<(const CTimer& t) const
00560 {
00561 return m_time < t.m_time;
00562 }