// ============================================================================ void IncidentSvc::removeListener ( IIncidentListener* lis , const std::string& type ) { boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex); if( type == "") { // remove Listener from all the lists ListenerMap::iterator itmap; for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();) { // since the current entry may be eventually deleted // we need to keep a memory of the next index before // calling recursively this method ListenerMap::iterator itmap_old = itmap; itmap++; removeListener( lis, (*itmap_old).first ); } } else { ListenerMap::iterator itmap = m_listenerMap.find( type ); if( itmap == m_listenerMap.end() ) { // if not found the incident type then return return; } else { ListenerList* llist = (*itmap).second; ListenerList::iterator itlist; bool justScheduleForRemoval = ( 0!= m_currentIncidentType ) && (type == *m_currentIncidentType); // loop over all the entries in the Listener list // to remove all of them than matches // the listener address. Remember the next index // before erasing the current one for( itlist = llist->begin(); itlist != llist->end(); ) { if( (*itlist).iListener == lis || lis == 0) { if (justScheduleForRemoval) { (itlist++)->singleShot = true; // remove it as soon as it is safe } else { DEBMSG << "Removing [" << type << "] listener '" << getListenerName(lis) << "'" << endmsg; itlist = llist->erase(itlist); // remove from the list now } } else { itlist++; } } if( llist->size() == 0) { delete llist; m_listenerMap.erase(itmap); } } } }
// ============================================================================ void IncidentSvc::i_fireIncident ( const Incident& incident , const std::string& listenerType ) { boost::recursive_mutex::scoped_lock lock(m_listenerMapMutex); // Special case: FailInputFile incident must set the application return code if (incident.type() == IncidentType::FailInputFile || incident.type() == IncidentType::CorruptedInputFile) { SmartIF<IProperty> appmgr(serviceLocator()); if (incident.type() == IncidentType::FailInputFile) // Set the return code to Gaudi::ReturnCode::FailInput (2) Gaudi::setAppReturnCode(appmgr, Gaudi::ReturnCode::FailInput).ignore(); else Gaudi::setAppReturnCode(appmgr, Gaudi::ReturnCode::CorruptedInput).ignore(); } ListenerMap::iterator itmap = m_listenerMap.find( listenerType ); if ( m_listenerMap.end() == itmap ) return; // setting this pointer will avoid that a call to removeListener() during // the loop triggers a segfault m_currentIncidentType = &(incident.type()); ListenerList* llist = (*itmap).second; ListenerList::iterator itlist; bool weHaveToCleanUp = false; // loop over all registered Listeners for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) { VERMSG << "Calling '" << getListenerName((*itlist).iListener) << "' for incident [" << incident.type() << "]" << endmsg; // handle exceptions if they occur try { (*itlist).iListener->handle(incident); } catch( const GaudiException& exc ) { error() << "Exception with tag=" << exc.tag() << " is caught" " handling incident" << m_currentIncidentType << endmsg; error() << exc << endmsg; if ( (*itlist).rethrow ) { throw (exc); } } catch( const std::exception& exc ) { error() << "Standard std::exception is caught" " handling incident" << m_currentIncidentType << endmsg; error() << exc.what() << endmsg; if ( (*itlist).rethrow ) { throw (exc); } } catch(...) { error() << "UNKNOWN Exception is caught" " handling incident" << m_currentIncidentType << endmsg; if ( (*itlist).rethrow ) { throw; } } // check if at least one of the listeners is a one-shot weHaveToCleanUp |= itlist->singleShot; } if (weHaveToCleanUp) { // remove all the listeners that need to be removed from the list llist->remove_if( listenerToBeRemoved() ); // if the list is empty, we can remove it if( llist->size() == 0) { delete llist; m_listenerMap.erase(itmap); } } m_currentIncidentType = 0; }