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