예제 #1
0
//---------------------------------------------------------------------------------------------------------------------
// 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;
}
예제 #2
0
//
// 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;
}
예제 #3
0
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;
}