Gaudi Framework, version v20r2

Generated: 18 Jul 2008

IncidentSvc.cpp

Go to the documentation of this file.
00001 // $Header: /local/reps/Gaudi/GaudiSvc/src/IncidentSvc/IncidentSvc.cpp,v 1.10 2008/02/08 17:23:35 marcocle Exp $
00002 
00003 // Include Files
00004 #include "GaudiKernel/MsgStream.h"
00005 #include "GaudiKernel/ISvcLocator.h"
00006 #include "GaudiKernel/SmartIF.h"
00007 #include "GaudiKernel/IIncidentListener.h"
00008 #include "GaudiKernel/Incident.h"
00009 #include "GaudiKernel/GaudiException.h"
00010 #include "IncidentSvc.h"
00011 
00012 // Instantiation of a static factory class used by clients to create
00013 //  instances of this service
00014 DECLARE_SERVICE_FACTORY(IncidentSvc)
00015 
00016 namespace {
00017   // Helper to get the name of the listener
00018   std::string getListenerName(IIncidentListener* lis)
00019   {
00020     SmartIF<INamedInterface> iNamed(lis);
00021     if (iNamed.isValid()) return iNamed->name();
00022     else return "<unknown>";  
00023   }
00024 }
00025 
00026 //============================================================================================
00027 // Constructors and Desctructors
00028 //============================================================================================
00029 IncidentSvc::IncidentSvc( const std::string& name, ISvcLocator* svc )
00030 : Service(name, svc),m_currentIncidentType(0) {
00031 }
00032 
00033 IncidentSvc::~IncidentSvc() { 
00034   for (ListenerMap::iterator i = m_listenerMap.begin();
00035        i != m_listenerMap.end();
00036        ++i) {
00037     delete i->second;
00038   }
00039 }
00040 
00041 //============================================================================================
00042 // Inherited Service overrides:
00043 //============================================================================================
00044 //
00045 StatusCode IncidentSvc::initialize() {
00046   // initialize the Service Base class
00047   StatusCode sc = Service::initialize();
00048   if ( sc.isFailure() ) {
00049     return sc;
00050   }
00051 
00052   MsgStream log( msgSvc(), name() ); 
00053 
00054   // set my own (IncidentSvc) properties via the jobOptionService 
00055   sc = setProperties();
00056   if ( sc.isFailure() ) {
00057     log << MSG::ERROR << "Could not set my properties" << endreq;
00058     return sc;
00059   }
00060 
00061   return StatusCode::SUCCESS;
00062 }
00063   
00064 StatusCode IncidentSvc::finalize() {
00065   // Finalize this specific service
00066   StatusCode sc = Service::finalize();
00067   if ( sc.isFailure() ) {
00068     return sc;
00069   }
00070 
00071   return StatusCode::SUCCESS;
00072 }
00073   
00074 StatusCode IncidentSvc::queryInterface( const InterfaceID& riid, void** ppvInterface ) {
00075   if ( IID_IIncidentSvc == riid )    {
00076     *ppvInterface = (IIncidentSvc*)this;
00077   }
00078   else  {
00079     // Interface is not directly available: try out a base class
00080     return Service::queryInterface(riid, ppvInterface);
00081   }
00082   addRef();
00083   return StatusCode::SUCCESS;
00084 }
00085   
00086 //============================================================================================
00087 // Inherited IIncidentSvc overrides:
00088 //============================================================================================
00089 //
00090 void IncidentSvc::addListener(IIncidentListener* lis, const std::string& type,
00091                                                 long prio, bool rethrow, bool singleShot) {
00092 
00093   std::string ltype;
00094   if( type == "" ) ltype = "ALL";
00095   else             ltype = type;
00096   // find if the type already exists
00097   ListenerMap::iterator itMap = m_listenerMap.find( ltype );
00098   if( itMap == m_listenerMap.end() ) {
00099     // if not found, create and insert now a list of listeners
00100     ListenerList* newlist = new ListenerList();
00101     std::pair<ListenerMap::iterator, bool> p;
00102     p = m_listenerMap.insert(ListenerMap::value_type(ltype, newlist));
00103     if( p.second ) itMap = p.first;
00104   }
00105   ListenerList* llist = (*itMap).second;
00106   // add Listener in the ListenerList according to the priority
00107   ListenerList::iterator itlist;
00108   for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
00109     if( (*itlist).priority < prio ) {
00110       // We insert before the current position
00111       break;
00112     }
00113   }
00114 
00115   MsgStream log ( msgSvc() , name());
00116   log << MSG::DEBUG << "Adding [" << type << "] listener '" << getListenerName(lis)
00117       << "' with priority " << prio << endreq;
00118   
00119   llist->insert(itlist, Listener(lis, prio, rethrow, singleShot));
00120   return;
00121 }
00122 
00123 void IncidentSvc::removeListener(IIncidentListener* lis, const std::string& type) {
00124 
00125   MsgStream log ( msgSvc() , name());
00126   if( type == "") {
00127     // remove Listener from all the lists
00128     ListenerMap::iterator itmap;
00129     for ( itmap = m_listenerMap.begin(); itmap != m_listenerMap.end();) {
00130       // since the current entry may be eventually deleted 
00131       // we need to keep a memory of the next index before calling recursivelly this method
00132       ListenerMap::iterator itmap_old = itmap;
00133       itmap++;
00134       removeListener( lis, (*itmap_old).first );
00135     }
00136   }
00137   else {
00138     ListenerMap::iterator itmap = m_listenerMap.find( type );
00139     if( itmap == m_listenerMap.end() ) {
00140       // if not found the incident type then return
00141       return;
00142     }
00143     else {
00144       ListenerList* llist = (*itmap).second;
00145       ListenerList::iterator itlist;
00146       bool justScheduleForRemoval = ( 0!= m_currentIncidentType )
00147                                     && (type == *m_currentIncidentType);
00148       // loop over all the entries in the Listener list to remove all of them than matches 
00149       // the listener address. Remember the next index before erasing the current one
00150       for( itlist = llist->begin(); itlist != llist->end(); ) {
00151         if( (*itlist).iListener == lis || lis == 0) {
00152           if (justScheduleForRemoval) {
00153             (itlist++)->singleShot = true; // remove it as soon as it is safe
00154           }
00155           else {
00156             log << MSG::DEBUG << "Removing [" << type << "] listener '"
00157                 << getListenerName(lis) << "'" << endreq;
00158             itlist = llist->erase(itlist); // remove from the list now
00159           }
00160         }
00161         else {
00162           itlist++;
00163         }
00164       }
00165       if( llist->size() == 0) {
00166         delete llist;
00167         m_listenerMap.erase(itmap);
00168       }
00169     }
00170   }
00171   return;
00172 }
00173 
00174 namespace {
00177         struct listenerToBeRemoved{
00178                 inline bool operator() (const IncidentSvc::Listener& l) {
00179                          return l.singleShot;
00180                 }
00181         };
00182 }
00183 
00184 void IncidentSvc::fireIncident( const Incident& incident ) {
00185         // setting this pointer will avoid that a call to removeListener() during
00186         // the loop triggers a segfault
00187   m_currentIncidentType = &(incident.type());
00188   
00189   MsgStream log ( msgSvc() , name());
00190   ListenerMap::iterator itmap = m_listenerMap.find( incident.type() );
00191   if( itmap != m_listenerMap.end() ) {
00192     ListenerList* llist = (*itmap).second;
00193     ListenerList::iterator itlist;
00194     bool weHaveToCleanUp = false;
00195     // loop over all registered Listeners
00196     for( itlist = llist->begin(); itlist != llist->end(); itlist++ ) {
00197       log << MSG::VERBOSE << "Calling '" << getListenerName((*itlist).iListener)
00198           << "' for incident [" << incident.type() << "]" << endreq;
00199 
00200       // handle exceptions if they occur
00201       try {
00202         (*itlist).iListener->handle(incident);
00203       }
00204       catch( const GaudiException& exc ) {
00205        log << MSG::ERROR << "Exception with tag=" << exc.tag() << " is caught " << endreq;
00206        log << MSG::ERROR <<  exc  << endreq;
00207        if ( (*itlist).rethrow ) { throw (exc); }
00208       }
00209       catch( const std::exception& exc ) {
00210        log << MSG::ERROR << "Standard std::exception is caught " << endreq;
00211        log << MSG::ERROR << exc.what()  << endreq;
00212        if ( (*itlist).rethrow ) { throw (exc); }
00213       }
00214       catch(...) {
00215        log << MSG::ERROR << "UNKNOWN Exception is caught " << endreq;
00216        if ( (*itlist).rethrow ) { throw; }
00217       }
00218       // check if at least one of the listeners is a one-shot
00219       weHaveToCleanUp |= itlist->singleShot;
00220     }
00221     if (weHaveToCleanUp) {
00222         // remove all the listeners that need to be removed from the list
00223         llist->remove_if( listenerToBeRemoved() );
00224         // if the list is empty, we can remove it
00225         if( llist->size() == 0) {
00226         delete llist;
00227         m_listenerMap.erase(itmap);
00228       }
00229     }
00230   } 
00231   m_currentIncidentType = NULL;
00232   return;
00233 }

Generated at Fri Jul 18 11:59:24 2008 for Gaudi Framework, version v20r2 by Doxygen version 1.5.1 written by Dimitri van Heesch, © 1997-2004