Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:57:36

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 /*
0012  * CommonMessaging.h
0013  *
0014  *  Created on: Feb 20, 2009
0015  *      Author: Marco Clemencic
0016  */
0017 
0018 #ifndef COMMONMESSAGING_H_
0019 #define COMMONMESSAGING_H_
0020 #include "GaudiKernel/GaudiException.h"
0021 #include "GaudiKernel/IMessageSvc.h"
0022 #include "GaudiKernel/IService.h"
0023 #include "GaudiKernel/ISvcLocator.h"
0024 #include "GaudiKernel/MsgStream.h"
0025 #include "GaudiKernel/SmartIF.h"
0026 #include "GaudiKernel/detected.h"
0027 #include <boost/thread/tss.hpp>
0028 
0029 #include <memory>
0030 #include <utility>
0031 
0032 /** Templated class to add the standard messaging functionalities
0033  *
0034  */
0035 
0036 #define generate_( method, ret, args )                                                                                 \
0037                                                                                                                        \
0038   template <typename T>                                                                                                \
0039   using _has_##method = decltype( std::declval<const T&>().method args );                                              \
0040                                                                                                                        \
0041   template <typename T>                                                                                                \
0042   using has_##method = Gaudi::cpp17::is_detected<_has_##method, T>;                                                    \
0043                                                                                                                        \
0044   template <typename Base>                                                                                             \
0045   struct add_##method : public Base {                                                                                  \
0046     using Base::Base;                                                                                                  \
0047     virtual ~add_##method()       = default;                                                                           \
0048     virtual ret method args const = 0;                                                                                 \
0049   };
0050 
0051 namespace implementation_detail {
0052   generate_( name, const std::string&, () )
0053 
0054       generate_( serviceLocator, SmartIF<ISvcLocator>&, () )
0055 }
0056 #undef generate_
0057 
0058 template <typename Base>
0059 using add_name =
0060     std::conditional_t<implementation_detail::has_name<Base>::value, Base, implementation_detail::add_name<Base>>;
0061 template <typename Base>
0062 using add_serviceLocator = std::conditional_t<implementation_detail::has_serviceLocator<Base>::value, Base,
0063                                               implementation_detail::add_serviceLocator<Base>>;
0064 
0065 template <typename Base>
0066 class CommonMessaging;
0067 
0068 class CommonMessagingBase {
0069 public:
0070   /// Virtual destructor
0071   virtual ~CommonMessagingBase() = default;
0072   /// cold functionality
0073   virtual void create_msgStream() const = 0;
0074 
0075   /** The standard message service.
0076    *  Returns a pointer to the standard message service.
0077    */
0078   const SmartIF<IMessageSvc>& msgSvc() const { return m_msgsvc; }
0079 
0080   /// Return an uninitialized MsgStream.
0081   MsgStream& msgStream() const {
0082     if ( !m_msgStream.get() ) create_msgStream();
0083     return *m_msgStream;
0084   }
0085 
0086   /** Predefined configurable message stream for the efficient printouts
0087    *
0088    *  @code
0089    *
0090    *  if ( a < 0 ) { msgStream( MSG::ERROR ) << "a = " << endmsg ; }
0091    *
0092    *  @endcode
0093    *
0094    *  @return Reference to the predefined stream
0095    */
0096   MsgStream& msgStream( const MSG::Level level ) const { return msgStream() << level; }
0097 
0098   /// shortcut for the method msgStream(MSG::ALWAYS)
0099   MsgStream& always() const { return msgStream( MSG::ALWAYS ); }
0100 
0101   /// shortcut for the method msgStream(MSG::FATAL)
0102   MsgStream& fatal() const { return msgStream( MSG::FATAL ); }
0103 
0104   /// shortcut for the method msgStream(MSG::ERROR)
0105   MsgStream& err() const { return msgStream( MSG::ERROR ); }
0106 
0107   /// shortcut for the method msgStream(MSG::ERROR)
0108   MsgStream& error() const { return msgStream( MSG::ERROR ); }
0109 
0110   /// shortcut for the method msgStream(MSG::WARNING)
0111   MsgStream& warning() const { return msgStream( MSG::WARNING ); }
0112 
0113   /// shortcut for the method msgStream(MSG::INFO)
0114   MsgStream& info() const { return msgStream( MSG::INFO ); }
0115 
0116   /// shortcut for the method msgStream(MSG::DEBUG)
0117   MsgStream& debug() const { return msgStream( MSG::DEBUG ); }
0118 
0119   /// shortcut for the method msgStream(MSG::VERBOSE)
0120   MsgStream& verbose() const { return msgStream( MSG::VERBOSE ); }
0121 
0122   /// shortcut for the method msgStream(MSG::INFO)
0123   MsgStream& msg() const { return msgStream( MSG::INFO ); }
0124 
0125 private:
0126   template <typename Base>
0127   friend class CommonMessaging;
0128 
0129   mutable bool       m_commonMessagingReady = false;
0130   mutable MSG::Level m_level                = MSG::NIL;
0131 
0132   /// The predefined message stream
0133   mutable boost::thread_specific_ptr<MsgStream> m_msgStream;
0134 
0135   /// Pointer to the message service;
0136   mutable SmartIF<IMessageSvc> m_msgsvc;
0137 };
0138 
0139 template <typename BASE>
0140 class GAUDI_API CommonMessaging : public add_serviceLocator<add_name<BASE>>, public CommonMessagingBase {
0141 public:
0142   using base_class = CommonMessaging;
0143 
0144   /// Forward constructor to base class constructor
0145   using add_serviceLocator<add_name<BASE>>::add_serviceLocator;
0146 
0147   /// get the cached level (originally extracted from the embedded MsgStream)
0148   MSG::Level msgLevel() const {
0149     if ( m_commonMessagingReady ) return m_level;
0150     return setUpMessaging();
0151   }
0152 
0153   /// get the output level from the embedded MsgStream
0154   bool msgLevel( MSG::Level lvl ) const { return msgLevel() <= lvl; }
0155 
0156 private:
0157   // out-of-line 'cold' functions -- put here so as to not blow up the inline 'hot' functions
0158   void create_msgStream() const override final { m_msgStream.reset( new MsgStream( msgSvc(), this->name() ) ); }
0159 
0160   /// Initialise the messaging objects
0161   void initMessaging() const {
0162     if ( !m_msgsvc ) {
0163       // Get default implementation of the message service.
0164       m_msgsvc = this->serviceLocator();
0165     }
0166     create_msgStream();
0167     m_level = MSG::Level( m_msgStream.get() ? m_msgStream->level() : MSG::NIL );
0168     // if we could not get a MessageSvc, we should try again the initial set up
0169     m_commonMessagingReady = m_msgsvc;
0170   }
0171 
0172 protected:
0173   /// Set up local caches
0174   MSG::Level setUpMessaging() const {
0175     if ( !m_commonMessagingReady ) { initMessaging(); }
0176     return m_level;
0177   }
0178   /// Reinitialize internal states.
0179   MSG::Level resetMessaging() {
0180     m_commonMessagingReady = false;
0181     return setUpMessaging();
0182   }
0183   /// Update the output level of the cached MsgStream.
0184   /// This function is meant to be called by the update handler of the OutputLevel property.
0185   void updateMsgStreamOutputLevel( int level ) {
0186     setUpMessaging();
0187     if ( level != MSG::NIL && level != m_level ) {
0188       if ( msgSvc() ) msgSvc()->setOutputLevel( this->name(), level );
0189       if ( m_msgStream.get() ) m_msgStream->setLevel( level );
0190       if ( MSG::Level( level ) <= MSG::DEBUG )
0191         debug() << "Property update for OutputLevel : new value = " << level << endmsg;
0192       m_level = MSG::Level( level );
0193     }
0194   }
0195 };
0196 
0197 #endif /* COMMONMESSAGING_H_ */