//--------------------------------------------------------------------------------------------------------------------- // EventManager::VTick //--------------------------------------------------------------------------------------------------------------------- bool EventManager::VUpdate(unsigned long maxMillis) { unsigned long currMs = GetTickCount(); unsigned long maxMs = ((maxMillis == IEventManager::kINFINITE) ? (IEventManager::kINFINITE) : (currMs + maxMillis)); // This section added to handle events from other threads. Check out Chapter 20. IEventDataPtr pRealtimeEvent; while (m_realtimeEventQueue.try_pop(pRealtimeEvent)) { VQueueEvent(pRealtimeEvent); currMs = GetTickCount(); if (maxMillis != IEventManager::kINFINITE) { if (currMs >= maxMs) { GCC_ERROR("A realtime process is spamming the event manager!"); } } } // swap active queues and clear the new queue after the swap int queueToProcess = m_activeQueue; m_activeQueue = (m_activeQueue + 1) % EVENTMANAGER_NUM_QUEUES; m_queues[m_activeQueue].clear(); GCC_LOG("EventLoop", "Processing Event Queue " + ToStr(queueToProcess) + "; " + ToStr((unsigned long)m_queues[queueToProcess].size()) + " events to process"); // Process the queue while (!m_queues[queueToProcess].empty()) { // pop the front of the queue IEventDataPtr pEvent = m_queues[queueToProcess].front(); m_queues[queueToProcess].pop_front(); GCC_LOG("EventLoop", "\t\tProcessing Event " + std::string(pEvent->GetName())); const EventType& eventType = pEvent->VGetEventType(); // find all the delegate functions registered for this event auto findIt = m_eventListeners.find(eventType); if (findIt != m_eventListeners.end()) { const EventListenerList& eventListeners = findIt->second; GCC_LOG("EventLoop", "\t\tFound " + ToStr((unsigned long)eventListeners.size()) + " delegates"); // call each listener for (auto it = eventListeners.begin(); it != eventListeners.end(); ++it) { EventListenerDelegate listener = (*it); GCC_LOG("EventLoop", "\t\tSending event " + std::string(pEvent->GetName()) + " to delegate"); listener(pEvent); } } // check to see if time ran out currMs = GetTickCount(); if (maxMillis != IEventManager::kINFINITE && currMs >= maxMs) { GCC_LOG("EventLoop", "Aborting event processing; time ran out"); break; } } // If we couldn't process all of the events, push the remaining events to the new active queue. // Note: To preserve sequencing, go back-to-front, inserting them at the head of the active queue bool queueFlushed = (m_queues[queueToProcess].empty()); if (!queueFlushed) { while (!m_queues[queueToProcess].empty()) { IEventDataPtr pEvent = m_queues[queueToProcess].back(); m_queues[queueToProcess].pop_back(); m_queues[m_activeQueue].push_front(pEvent); } } return queueFlushed; }
// // EventManager::VTick - Chapter 10, page 296 // EventManager::VTick - Chapter 18, page 671 (for the threadsafe stuff) // // Allow for processing of any queued messages, optionally // specify a processing time limit so that the event processing // does not take too long. Note the danger of using this // artificial limiter is that all messages may not in fact get // processed. // // returns true if all messages ready for processing were // completed, false otherwise (e.g. timeout ) // bool EventManager::VTick ( unsigned long maxMillis ) { unsigned long curMs = GetTickCount(); unsigned long maxMs = maxMillis == IEventManager::kINFINITE ? IEventManager::kINFINITE : (curMs + maxMillis ); EventListenerMap::const_iterator itWC = m_registry.find( 0 ); // This section added to handle events from other threads // Check out Chapter 18 // -------------------------------------------------------- IEventDataPtr rte; while (m_RealtimeEventQueue.try_pop(rte)) { VQueueEvent(rte); curMs = GetTickCount(); if ( maxMillis != IEventManager::kINFINITE ) { if ( curMs >= maxMs ) { assert(0 && "A realtime process is spamming the event manager!"); } } } // -------------------------------------------------------- // swap active queues, make sure new queue is empty after the // swap ... int queueToProcess = m_activeQueue; m_activeQueue = ( m_activeQueue + 1 ) % kNumQueues; m_queues[m_activeQueue].clear(); // now process as many events as we can ( possibly time // limited ) ... always do AT LEAST one event, if ANY are // available ... while ( m_queues[queueToProcess].size() > 0 ) { IEventDataPtr event = m_queues[queueToProcess].front(); m_queues[queueToProcess].pop_front(); EventType const & eventType = event->VGetEventType(); EventListenerMap::const_iterator itListeners = m_registry.find( eventType.getHashValue() ); if ( itWC != m_registry.end() ) { EventListenerTable const & table = itWC->second; bool processed = false; for ( EventListenerTable::const_iterator it2 = table.begin(), it2End = table.end(); it2 != it2End; it2++ ) { (*it2)->HandleEvent( *event ); } } // no listerners currently for this event type, skipit if ( itListeners == m_registry.end() ) continue; unsigned int const kEventId = itListeners->first; EventListenerTable const & table = itListeners->second; for ( EventListenerTable::const_iterator it = table.begin(), end = table.end(); it != end ; it++ ) { if ( (*it)->HandleEvent( *event ) ) { break; } } curMs = GetTickCount(); if ( maxMillis != IEventManager::kINFINITE ) { if ( curMs >= maxMs ) { // time ran about, abort processing loop break; } } } // if any events left to process, push them onto the active // queue. // // Note: to preserver sequencing, go bottom-up on the // raminder, inserting them at the head of the active // queue... bool queueFlushed = ( m_queues[queueToProcess].size() == 0 ); if ( !queueFlushed ) { while ( m_queues[queueToProcess].size() > 0 ) { IEventDataPtr event = m_queues[queueToProcess].back(); m_queues[queueToProcess].pop_back(); m_queues[m_activeQueue].push_front( event ); } } // all done, this pass return queueFlushed; }
bool EventManager::VUpdate(unsigned long maxMs) { unsigned long curMs = GetTickCount(); unsigned long computedMaxMs = (maxMs == IEventManager::kINFINITE ? IEventManager::kINFINITE : curMs + maxMs); EventDataPtr pRealtimeEvent; while (m_realtimeEventQueue.try_pop(pRealtimeEvent)) { VQueueEvent(pRealtimeEvent); curMs = GetTickCount(); if (maxMs != IEventManager::kINFINITE) { if (curMs >= computedMaxMs) { BE_ERROR("Realtime Proccess is spamming Event Manager!"); } } } int queueToProcess = m_activeQueue; m_activeQueue = (m_activeQueue + 1) % EVENTMANAGER_NUM_QUEUES; m_queues[m_activeQueue].clear(); while (!m_queues[queueToProcess].empty()) { EventDataPtr pEvent = m_queues[queueToProcess].front(); m_queues[queueToProcess].pop_front(); const EventType& eventType = pEvent->VGetEventType(); auto findIt = m_eventListeners.find(eventType); if (findIt != m_eventListeners.end()) { const EventListenerList& eventListeners = findIt->second; for (auto it = eventListeners.begin(); it != eventListeners.end(); it++) { EventListenerDelegate listener = (*it); listener(pEvent); } } curMs = GetTickCount(); if (maxMs != IEventManager::kINFINITE && curMs >= computedMaxMs) { //Abort, ran out of time break; } } //If couldnt process all, push remaining to new active queue bool queueFlushed = m_queues[queueToProcess].empty(); if (!queueFlushed) { while (!m_queues[queueToProcess].empty()) { EventDataPtr pEvent = m_queues[queueToProcess].back(); m_queues[queueToProcess].pop_back(); m_queues[m_activeQueue].push_front(pEvent); } } return queueFlushed; }