// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// bool EventManager::VAddListener(EventListenerPtr const &inListener, EventType const & inType) { if ( ! VValidateType( inType ) ) return false; // check / update type list EventTypeSet::iterator evIt = m_typeList.find( inType ); // find listener map entry, create one if no table already // exists for this entry ... EventListenerMap::iterator elmIt = m_registry.find( inType.getHashValue() ); if ( elmIt == m_registry.end() ) { EventListenerMapIRes elmIRes = m_registry.insert( EventListenerMapEnt( inType.getHashValue(), EventListenerTable() ) ); // whoops, could not insert into map!?!? if ( elmIRes.second == false ) return false; // should not be possible, how did we insert and create // an empty table!?!?! if ( elmIRes.first == m_registry.end() ) return false; // store it so we can update the mapped list next ... elmIt = elmIRes.first; } // update the mapped list of listeners, walk the existing // list (if any entries) to prevent duplicate addition of // listeners. This is a bit more costly at registration time // but will prevent the hard-to-notice duplicate event // propogation sequences that would happen if double-entries // were allowed. // note: use reference to make following code more simple EventListenerTable & evlTable = (*elmIt).second; for ( EventListenerTable::iterator it = evlTable.begin(), itEnd = evlTable.end(); it != itEnd ; it++ ) { bool bListenerMatch = ( *it == inListener ); if ( bListenerMatch ) return false; } // okay, event type validated, event listener validated, // event listener not already in map, add it evlTable.push_back( inListener ); return true; }
// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// EventListenerList EventManager::GetListenerList(EventType const &eventType) const { // invalid event type, so sad if ( ! VValidateType( eventType ) ) return EventListenerList(); EventListenerMap::const_iterator itListeners = m_registry.find( eventType.getHashValue() ); // no listerners currently for this event type, so sad if ( itListeners == m_registry.end() ) return EventListenerList(); EventListenerTable const & table = itListeners->second; // there was, but is not now, any listerners currently for // this event type, so sad if ( table.size() == 0 ) return EventListenerList(); EventListenerList result; result.reserve( table.size() ); for ( EventListenerTable::const_iterator it = table.begin(), end = table.end(); it != end ; it++ ) { result.push_back( *it ); } return result; }
// // EventManager::VValidateType - Chapter 10, page 299 // // Validate an event type, this does NOT add it to the internal // registry, only verifies that it is legal ( e.g. either the // ident number is not yet assigned, or it is assigned to // matching signature text, and the signature text is not empty // ). // bool cEventManager::VValidateType( EventType const & inType ) const{ if ( 0 == inType.getStr().length() ) return false; if ( ( inType.getHashValue() == 0 ) && (strcmp(inType.getStr().c_str(),kpWildcardEventType) != 0) ) return false; EventTypeSet::const_iterator evIt = m_typeList.find( inType ); if ( evIt == m_typeList.end() ){ printf("Event Failed validation: not registered with the EventManager!\n"); return false; } return true; }
// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// bool EventManager::VValidateType(EventType const &inType) const { if ( 0 == inType.getStr().length() ) return false; if ( ( inType.getHashValue() == 0 ) && (strcmp(inType.getStr().c_str(),kpWildcardEventType) != 0) ) return false; EventTypeSet::const_iterator evIt = m_typeList.find( inType ); if ( evIt == m_typeList.end() ) { assert( 0 && "Failed validation of an event type; it was probably not registered with the EventManager!" ); return false; } return true; }
// // EventManager::VAbortEvent - Chapter 10, page 295 // // Find the next-available instance of the named event type and // remove it from the processing queue. // // This may be done up to the point that it is actively being // processed ... e.g.: is safe to happen during event processing // itself. // // returns true if the event was found and removed, false // otherwise // bool EventManager::VAbortEvent ( EventType const & inType, bool allOfType ) { assert ( m_activeQueue >= 0 ); assert ( m_activeQueue < kNumQueues ); if ( ! VValidateType( inType ) ) return false; EventListenerMap::iterator it = m_registry.find( inType.getHashValue() ); if ( it == m_registry.end() ) return false; // no listeners for this event, skipit bool rc = false; // See a good discussion on this code here: // http://www.mcshaffry.com/GameCode/thread.php?threadid=517&sid= EventQueue &evtQueue = m_queues[m_activeQueue]; for ( EventQueue::iterator it = evtQueue.begin(), itEnd = evtQueue.end(); it != itEnd; it++ ) { if ( (*it)->VGetEventType() == inType ) { it = evtQueue.erase(it); rc = true; if ( !allOfType ) break; } else { ++it; } } return rc; }