![]() |
|
|||
File indexing completed on 2025-02-21 10:00:30
0001 /***********************************************************************************\ 0002 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations * 0003 * * 0004 * This software is distributed under the terms of the Apache version 2 licence, * 0005 * copied verbatim in the file "LICENSE". * 0006 * * 0007 * In applying this licence, CERN does not waive the privileges and immunities * 0008 * granted to it by virtue of its status as an Intergovernmental Organization * 0009 * or submit itself to any jurisdiction. * 0010 \***********************************************************************************/ 0011 #ifndef GAUDIKERNEL_GUARDS_H 0012 #define GAUDIKERNEL_GUARDS_H 1 0013 // ============================================================================ 0014 // Include files 0015 // ============================================================================ 0016 // STD & STL 0017 // ============================================================================ 0018 #include <exception> 0019 // ============================================================================ 0020 // GaudiKernel 0021 // ============================================================================ 0022 #include "GaudiKernel/IAuditor.h" 0023 #include "GaudiKernel/IExceptionSvc.h" 0024 #include "GaudiKernel/INamedInterface.h" 0025 #include "GaudiKernel/SmartIF.h" 0026 // ============================================================================ 0027 // forward declaration 0028 // ============================================================================ 0029 class GaudiException; 0030 // ============================================================================ 0031 namespace Gaudi { 0032 /** @namespace Gaudi::Guards Guards.h GaudiKernel/Guards.h 0033 * Collection of very simple classes which allows to 0034 * execution of some functions within the given well-defined 0035 * and exception-safe context. 0036 * In addition these utilities allow to remove many 0037 * ugly lines from many ancient base classes 0038 * 0039 * The namespace contains two simple guards: 0040 * - class Gaudi::Guards::ExceptionGuard 0041 * - class Gaudi::Guards::AuditorGuard 0042 * 0043 * Please note tha the class Gaudi::Utils::AlgContext is also 0044 * some kind of "guard". 0045 * 0046 * All these guards could work together in very collaborative way: 0047 * 0048 * @code 0049 * 0050 * StatusCode Algorithm::sysInitialize () 0051 * { 0052 * // create the message stream: 0053 * MsgStream log ( msgSvc() , name() ) ; 0054 * 0055 * // lock the scope for Auditor Service 0056 * Gaudi::Guards::AuditorGuard auditor 0057 * ( this , 0058 * auditorSvc() , ///< Auditor Service 0059 * &IAuditorSvc::beforeInitialize , ///< "pre"-action 0060 * &IAuditorsvc::afterInitialize ) ; ///< "post"-action 0061 * 0062 * // Lock the scope for Algorithm Context Service: 0063 * Gaudi::Utils::AlgContext context ( this , m_contextSvc ) ; 0064 * 0065 * // execute IAlgorithm::initialize within "try{}catch(..)" clause: 0066 * Gaudi::Guards::ExceptionGuard guard 0067 * ( this , ///< OBJECT 0068 * std::mem_fn(&IAlgorithm::initialize) , ///< FUNCTOR 0069 * log , ///< STREAM 0070 * m_exceptionSvc ) ; ///< (optional) Exception Service 0071 * 0072 * return guard ; /// return the result of functor evaluation 0073 * } 0074 * @endcode 0075 * 0076 * C++ guarantees the proper execution of all "post"-actions for all 0077 * involved guards when the scope is destroyed. 0078 * 0079 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 0080 * @date 2007-03-07 0081 */ 0082 namespace Guards { 0083 /** @class ExceptionGuard Guards.h GaudiKernel/Guards.h 0084 * The most simple guard - it execute the certain code 0085 * withing typical "try {} catch" clause, used in 0086 * Auditor, Algorithm, AlgTool, etc.. classes 0087 * 0088 * The usage is fairly trivial: 0089 * 0090 * @code 0091 * 0092 * // get the stream: 0093 * MsgStream& log = ... ; 0094 * 0095 * // create the guard object and execute this->initialize() 0096 * // within the standard "try"-clause: 0097 * Gaudi::Guards::Guard guard 0098 * ( this , ///< OBJECT 0099 * std::mem_fn(&IAuditor::initialize) , ///< FUNCTOR 0100 * log ) ; ///< stream 0101 * 0102 * // extract the status code" 0103 * StatusCode sc = guard.code() ; 0104 * 0105 * @endcode 0106 * 0107 * The utility could be reused for member-function, regular functions, etc.. 0108 * It could be easily combined with STL-idioms 0109 * Essentially it required only the semantical validity of the 0110 * expression "StatusCode sc = fun(obj)" 0111 * 0112 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 0113 * @date 2007-03-07 0114 */ 0115 class GAUDI_API ExceptionGuard { 0116 public: 0117 /* constructor form the object/scope, function and log-stream 0118 * @param obj the object/scope 0119 * @param fun function to be used 0120 * @param log output log-stream 0121 */ 0122 template <class OBJECT, class FUNCTION> 0123 ExceptionGuard( OBJECT obj, FUNCTION fun, MsgStream& log, IExceptionSvc* svc = 0 ) { 0124 try { 0125 // execute the functor: 0126 m_sc = fun( obj ); ///< execute the functor 0127 // in the case of error try use Exception Service 0128 if ( svc && m_sc.isFailure() ) { m_sc = svc->handleErr( *obj, m_sc ); } 0129 } catch ( const GaudiException& e ) { 0130 // Use the local handler and then (if possible) the Exception Service 0131 handle( e, log ); 0132 if ( svc ) { m_sc = svc->handle( *obj, e ); } 0133 } catch ( const std::exception& e ) { 0134 // Use the local handler and then (if possible) the Exception Service 0135 handle( e, log ); 0136 if ( svc ) { m_sc = svc->handle( *obj, e ); } 0137 } catch ( ... ) { 0138 // Use the local handler and then (if possible) the Exception Service 0139 handle( log ); 0140 if ( svc ) { m_sc = svc->handle( *obj ); } 0141 } 0142 } 0143 /// destructor 0144 ~ExceptionGuard(); 0145 0146 public: 0147 /// the result of function evaluation 0148 const StatusCode& code() const { return m_sc; } 0149 /// cast operator, useful for the implicit conversions 0150 operator const StatusCode&() const { return code(); } 0151 0152 private: 0153 // delete default/copy constructor and assignment 0154 ExceptionGuard() = delete; 0155 ExceptionGuard( const ExceptionGuard& ) = delete; 0156 ExceptionGuard& operator=( const ExceptionGuard& ) = delete; 0157 0158 protected: 0159 /// local handler of GaudiException 0160 void handle( const GaudiException& e, MsgStream& s ); 0161 /// local handler of std::exception 0162 void handle( const std::exception& e, MsgStream& s ); 0163 /// local handler of UNKNOWN exceptions 0164 void handle( MsgStream& s ); 0165 0166 private: 0167 // status code: result of the function evaluation 0168 StatusCode m_sc = StatusCode::FAILURE; ///< status code : result of function evaluation 0169 }; 0170 // ======================================================================== 0171 /** @class AuditorGuard Guards.h GaudiKernel/Guards.h 0172 * It is a simple guard, 0173 * which "locks" the scope for the Auditor Service 0174 * is am exception-safe way 0175 * 0176 * The pattern ensures that "post-action" will be always executed 0177 * 0178 * @code 0179 * 0180 * StatusCode Algorithm::sysInitialize () 0181 * { 0182 * AuditorGuard auditor ( this , 0183 * auditSvc() , ///< pointer to Auditor Service 0184 * IAuditor::Initialize ) ; ///< event to audit 0185 * ... 0186 * StatusCode sc = ... ; 0187 * ... 0188 * return sc ; ///< RETURN 0189 * } 0190 * 0191 * @endcode 0192 * 0193 * @code 0194 * 0195 * StatusCode Algorithm::sysExecute () 0196 * { 0197 * AuditorGuard auditor ( this , 0198 * auditSvc() , ///< pointer to Auditor Service 0199 * IAuditor::execute ) ; ///< event to audit 0200 * ... 0201 * StatusCode sc = ... ; 0202 * ... 0203 * auditor.setCode ( sc ) ; 0204 * ... 0205 * return sc ; ///< RETURN 0206 * } 0207 * 0208 * @endcode 0209 * 0210 * @author Vanya BELYAEV ibelyaev@physics.syr.edu 0211 * @date 2007-03-07 0212 */ 0213 class GAUDI_API AuditorGuard final { 0214 public: 0215 /// constructor 0216 AuditorGuard( INamedInterface* obj, IAuditor* svc, IAuditor::StandardEventType evt ); 0217 /// constructor 0218 AuditorGuard( INamedInterface* obj, IAuditor* svc, IAuditor::CustomEventTypeRef evt ); 0219 0220 /// constructor 0221 AuditorGuard( INamedInterface* obj, IAuditor* svc, IAuditor::StandardEventType evt, const StatusCode& sc ); 0222 /// constructor 0223 AuditorGuard( INamedInterface* obj, IAuditor* svc, IAuditor::CustomEventTypeRef evt, const StatusCode& sc ); 0224 /// constructor 0225 AuditorGuard( std::string name, IAuditor* svc, IAuditor::StandardEventType evt ); 0226 /// constructor 0227 AuditorGuard( std::string name, IAuditor* svc, IAuditor::CustomEventTypeRef evt ); 0228 0229 /// constructor 0230 AuditorGuard( std::string name, IAuditor* svc, IAuditor::StandardEventType evt, const StatusCode& sc ); 0231 /// constructor 0232 AuditorGuard( std::string name, IAuditor* svc, IAuditor::CustomEventTypeRef evt, const StatusCode& sc ); 0233 0234 /// dectructor 0235 ~AuditorGuard(); 0236 0237 public: 0238 // get the status code 0239 const StatusCode& code() const { return *m_sc; } 0240 0241 private: 0242 // delete the default/copy constructor and assigment 0243 AuditorGuard() = delete; 0244 AuditorGuard( const AuditorGuard& right ) = delete; 0245 AuditorGuard& operator=( const AuditorGuard& right ) = delete; 0246 0247 private: 0248 /// the guarded object 0249 INamedInterface* m_obj = nullptr; 0250 /// the guarded object name (if there is no INamedInterface) 0251 std::string m_objName; 0252 /// auditor service 0253 SmartIF<IAuditor> m_svc = nullptr; 0254 /// Event type (standard events) 0255 IAuditor::StandardEventType m_evt; 0256 /// Event type (custom events) 0257 IAuditor::CustomEventType m_cevt; 0258 /// Pointer to a status code instance, to be passed to the "after" function if needed 0259 /// The instance must have a scope larger than the one of the guard. 0260 /// No check is performed. 0261 const StatusCode* m_sc = nullptr; 0262 /// Flag to remember which event type was used. 0263 bool m_customEvtType = false; 0264 0265 inline void i_before() { 0266 if ( m_svc ) { // if the service is not available, we cannot do anything 0267 if ( m_obj ) { 0268 if ( m_customEvtType ) { 0269 m_svc->before( m_cevt, m_obj ); 0270 } else { 0271 m_svc->before( m_evt, m_obj ); 0272 } 0273 } else { // use object name 0274 if ( m_customEvtType ) { 0275 m_svc->before( m_cevt, m_objName ); 0276 } else { 0277 m_svc->before( m_evt, m_objName ); 0278 } 0279 } 0280 } 0281 } 0282 0283 inline void i_after() { 0284 if ( m_svc ) { // if the service is not available, we cannot do anything 0285 if ( m_obj ) { 0286 if ( m_customEvtType ) { 0287 if ( m_sc ) { 0288 m_svc->after( m_cevt, m_obj, *m_sc ); 0289 } else { 0290 m_svc->after( m_cevt, m_obj ); 0291 } 0292 } else { 0293 if ( m_sc ) { 0294 m_svc->after( m_evt, m_obj, *m_sc ); 0295 } else { 0296 m_svc->after( m_evt, m_obj ); 0297 } 0298 } 0299 } else { // use object name 0300 if ( m_customEvtType ) { 0301 if ( m_sc ) { 0302 m_svc->after( m_cevt, m_objName, *m_sc ); 0303 } else { 0304 m_svc->after( m_cevt, m_objName ); 0305 } 0306 } else { 0307 if ( m_sc ) { 0308 m_svc->after( m_evt, m_objName, *m_sc ); 0309 } else { 0310 m_svc->after( m_evt, m_objName ); 0311 } 0312 } 0313 } 0314 m_svc.reset(); 0315 } 0316 } 0317 }; 0318 } // namespace Guards 0319 } // end of namespace Gaudi 0320 0321 // ============================================================================ 0322 // The END 0323 // ============================================================================ 0324 #endif // GAUDIKERNEL_GUARDS_H
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |