// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// bool EventManager::VQueueEvent ( IEventDataPtr const & inEvent ) { assert ( m_activeQueue >= 0 ); assert ( m_activeQueue < kNumQueues ); if ( ! VValidateType( inEvent->VGetEventType() ) ) return false; EventListenerMap::const_iterator it = m_registry.find( inEvent->VGetEventType().getHashValue() ); if ( it == m_registry.end() ) { // if global listener is not active, then abort queue add EventListenerMap::const_iterator itWC = m_registry.find( 0 ); if ( itWC == m_registry.end() ) { // no listeners for this event, skipit return false; } } m_queues[m_activeQueue].push_back( inEvent ); return true; }
//--------------------------------------------------------------------------------------------------------------------- // EventManager::VQueueEvent //--------------------------------------------------------------------------------------------------------------------- bool EventManager::VQueueEvent(const IEventDataPtr& pEvent) { GCC_ASSERT(m_activeQueue >= 0); GCC_ASSERT(m_activeQueue < EVENTMANAGER_NUM_QUEUES); // make sure the event is valid if (!pEvent) { GCC_ERROR("Invalid event in VQueueEvent()"); return false; } GCC_LOG("Events", "Attempting to queue event: " + std::string(pEvent->GetName())); auto findIt = m_eventListeners.find(pEvent->VGetEventType()); if (findIt != m_eventListeners.end()) { m_queues[m_activeQueue].push_back(pEvent); GCC_LOG("Events", "Successfully queued event: " + std::string(pEvent->GetName())); return true; } else { GCC_LOG("Events", "Skipping event since there are no delegates registered to receive it: " + std::string(pEvent->GetName())); return false; } }
void NetworkEventForwarder::ForwardEvent(IEventDataPtr pEventData) { std::ostrstream out; out << static_cast<int>(RemoteEventSocket::NetMsg_Event) << " "; out << pEventData->VGetEventType() << " "; pEventData->VSerialize(out); out << "\r\n"; std::shared_ptr<BinaryPacket> eventMsg(GCC_NEW BinaryPacket(out.rdbuf()->str(), out.pcount())); g_pSocketManager->Send(m_sockId, eventMsg); }
//--------------------------------------------------------------------------------------------------------------------- // EventManager::VTrigger //--------------------------------------------------------------------------------------------------------------------- bool EventManager::VTriggerEvent(const IEventDataPtr& pEvent) const { GCC_LOG("Events", "Attempting to trigger event " + std::string(pEvent->GetName())); bool processed = false; auto findIt = m_eventListeners.find(pEvent->VGetEventType()); if (findIt != m_eventListeners.end()) { const EventListenerList& eventListenerList = findIt->second; for (EventListenerList::const_iterator it = eventListenerList.begin(); it != eventListenerList.end(); ++it) { EventListenerDelegate listener = (*it); GCC_LOG("Events", "Sending Event " + std::string(pEvent->GetName()) + " to delegate."); listener(pEvent); // call the delegate processed = true; } } return processed; }
// ///////////////////////////////////////////////////////////////// // GameTimer version. // // ///////////////////////////////////////////////////////////////// bool EventManager::VTick (U64 maxMillis) { //// Reset listeners removed flag upon entry. //m_listenersRemoved = false; // Create and start a timer on entry. shared_ptr<IGameTimer> timer(GCC_NEW GlfwGameTimer()); timer->VStart(); EventListenerMap::const_iterator itWC = m_registry.find( 0 ); // TODO: Implement this when i get multiprogramming chapter done. //// 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 ... I32 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() ); // Handle of events of type wildcard if ( itWC != m_registry.end() ) { EventListenerTable const & table = itWC->second; for(EventListenerTable::const_iterator it2 = table.begin(); it2 != table.end(); ++it2 ) { (*it2)->VHandleEvent( *event ); } } // no listerners currently for this event type, skipit if ( itListeners == m_registry.end() ) continue; EventListenerTable const & table = itListeners->second; // Handle all events of the current type in the queue for(EventListenerTable::const_iterator it = table.begin(); it != table.end(); ++it) { if ( (*it)->VHandleEvent( *event ) ) { break; } } if ( maxMillis != IEventManager::kINFINITE ) { if ( static_cast<U64>(timer->VGetTime()) >= maxMillis ) { // 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; }
// // 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; }
//--------------------------------------------------------------------------------------------------------------------- // 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; }