From 7d9b176480bbbbc3baac8b6fdfab62794791b649 Mon Sep 17 00:00:00 2001 From: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Mon, 17 Jun 2024 16:13:14 +0200 Subject: [PATCH] Introduced ICallBackHolder and CallBackHolder wrapper This allows to register callbacks are each State transition of a component. It can be an alternative to overwriting initialize/start/stop/finalize methods in particular. --- GaudiKernel/include/Gaudi/FSMCallbackHolder.h | 69 +++++++++++++++++++ .../Gaudi/Interfaces/IFSMCallbackHolder.h | 30 ++++++++ GaudiTestSuite/CMakeLists.txt | 1 + GaudiTestSuite/options/FSMCallbackTest.py | 15 ++++ .../src/FSMCallback/FSMCallbackTestAlgo.cpp | 34 +++++++++ .../qmtest/gauditestsuite.qms/callback.qmt | 16 +++++ .../tests/qmtest/refs/FSMCallbackTest.ref | 26 +++++++ 7 files changed, 191 insertions(+) create mode 100644 GaudiKernel/include/Gaudi/FSMCallbackHolder.h create mode 100644 GaudiKernel/include/Gaudi/Interfaces/IFSMCallbackHolder.h create mode 100644 GaudiTestSuite/options/FSMCallbackTest.py create mode 100644 GaudiTestSuite/src/FSMCallback/FSMCallbackTestAlgo.cpp create mode 100644 GaudiTestSuite/tests/qmtest/gauditestsuite.qms/callback.qmt create mode 100644 GaudiTestSuite/tests/qmtest/refs/FSMCallbackTest.ref diff --git a/GaudiKernel/include/Gaudi/FSMCallbackHolder.h b/GaudiKernel/include/Gaudi/FSMCallbackHolder.h new file mode 100644 index 0000000000..e7ada4ff60 --- /dev/null +++ b/GaudiKernel/include/Gaudi/FSMCallbackHolder.h @@ -0,0 +1,69 @@ +/***********************************************************************************\ +* (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations * +* * +* This software is distributed under the terms of the Apache version 2 licence, * +* copied verbatim in the file "LICENSE". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\***********************************************************************************/ +#pragma once + +#include <Gaudi/Interfaces/IFSMCallbackHolder.h> +#include <GaudiKernel/StateMachine.h> +#include <GaudiKernel/extends.h> + +#include <map> +#include <vector> + +namespace Gaudi { + + /** Helper class to implement the IFSMCallbackHolder interface. + * + * FSMCallbackHolder is used by components base classes (Algorithm, Tool, + * etc.) to provide a default implementation the IFSMCallbackHolder interface. + * + * When needing to implement the IFSMCallbackHolder interface in a class, it is + * enough to wrap the base of the class with FSMCallbackHolder, as in + * + * \code{.cpp} + * class MyClass : public FSMCallbackHolder<BaseClass> { + * // ... + * }; + * \endcode + */ + template <class BASE> + class FSMCallbackHolder : public extends<BASE, IFSMCallbackHolder> { + + public: + using Parent = extends<BASE, IFSMCallbackHolder>; + using extends<BASE, IFSMCallbackHolder>::extends; + + void registerCallBack( StateMachine::Transition s, IFSMCallbackHolder::CallBack c ) override { + m_callbacks[s].push_back( std::move( c ) ); + } + + StatusCode sysInitialize() override { + return Parent::sysInitialize().andThen( [&]() { handleCallBacks( StateMachine::INITIALIZE ); } ); + } + StatusCode sysStart() override { + return Parent::sysStart().andThen( [&]() { handleCallBacks( StateMachine::START ); } ); + } + StatusCode sysStop() override { + return Parent::sysStop().andThen( [&]() { handleCallBacks( StateMachine::STOP ); } ); + } + StatusCode sysFinalize() override { + return Parent::sysFinalize().andThen( [&]() { handleCallBacks( StateMachine::FINALIZE ); } ); + } + + private: + void handleCallBacks( StateMachine::Transition state ) { + std::for_each( m_callbacks[state].begin(), m_callbacks[state].end(), + []( IFSMCallbackHolder::CallBack const& c ) { c(); } ); + } + + std::map<StateMachine::Transition, std::vector<IFSMCallbackHolder::CallBack>> m_callbacks; + }; + +} // namespace Gaudi diff --git a/GaudiKernel/include/Gaudi/Interfaces/IFSMCallbackHolder.h b/GaudiKernel/include/Gaudi/Interfaces/IFSMCallbackHolder.h new file mode 100644 index 0000000000..bb70724196 --- /dev/null +++ b/GaudiKernel/include/Gaudi/Interfaces/IFSMCallbackHolder.h @@ -0,0 +1,30 @@ +/***********************************************************************************\ +* (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations * +* * +* This software is distributed under the terms of the Apache version 2 licence, * +* copied verbatim in the file "LICENSE". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\***********************************************************************************/ +#pragma once + +#include <GaudiKernel/StateMachine.h> + +namespace Gaudi { + /** + * Interface defining a CallBack registration functionality based on the + * State Machine of Gaudi. Callbacks are std::function which can be registered + * for each transition. They will then be called automatically just after + * the transition took place in the order in which they have been registered. + */ + struct IFSMCallbackHolder : virtual public IInterface { + + public: + DeclareInterfaceID( IFSMCallbackHolder, 1, 0 ); + + using CallBack = std::function<void()>; + virtual void registerCallBack( StateMachine::Transition, CallBack ) = 0; + }; +} // namespace Gaudi diff --git a/GaudiTestSuite/CMakeLists.txt b/GaudiTestSuite/CMakeLists.txt index 4a84a4fd6b..0434723398 100644 --- a/GaudiTestSuite/CMakeLists.txt +++ b/GaudiTestSuite/CMakeLists.txt @@ -55,6 +55,7 @@ gaudi_add_module(GaudiTestSuiteComponents src/ExtendedProperties/ExtendedProperties.cpp src/ExtendedProperties/ExtendedProperties2.cpp src/FileMgr/FileMgrTest.cpp + src/FSMCallback/FSMCallbackTestAlgo.cpp src/FunctionalAlgorithms/EventCounter.cpp src/FunctionalAlgorithms/MakeAndConsume.cpp src/FunctionalAlgorithms/merging_transformer.cpp diff --git a/GaudiTestSuite/options/FSMCallbackTest.py b/GaudiTestSuite/options/FSMCallbackTest.py new file mode 100644 index 0000000000..26e303452b --- /dev/null +++ b/GaudiTestSuite/options/FSMCallbackTest.py @@ -0,0 +1,15 @@ +##################################################################################### +# (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations # +# # +# This software is distributed under the terms of the Apache version 2 licence, # +# copied verbatim in the file "LICENSE". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +##################################################################################### +from Gaudi.Configuration import ApplicationMgr +from Configurables import Gaudi__TestSuite__FSMCallbackTestAlgo as FSMCallbackTestAlgo + +alg = FSMCallbackTestAlgo("CallBackTestAlgo") +app = ApplicationMgr(EvtMax=5, EvtSel="NONE", TopAlg=[alg]) diff --git a/GaudiTestSuite/src/FSMCallback/FSMCallbackTestAlgo.cpp b/GaudiTestSuite/src/FSMCallback/FSMCallbackTestAlgo.cpp new file mode 100644 index 0000000000..ade8fcee63 --- /dev/null +++ b/GaudiTestSuite/src/FSMCallback/FSMCallbackTestAlgo.cpp @@ -0,0 +1,34 @@ +/***********************************************************************************\ +* (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations * +* * +* This software is distributed under the terms of the Apache version 2 licence, * +* copied verbatim in the file "LICENSE". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\***********************************************************************************/ +#include <Gaudi/Algorithm.h> +#include <Gaudi/FSMCallbackHolder.h> + +namespace Gaudi::TestSuite { + + /** + * Example of usage of callbacks, when using CallbackHolder + */ + struct FSMCallbackTestAlgo : FSMCallbackHolder<Algorithm> { + FSMCallbackTestAlgo( const std::string& name, ISvcLocator* pSvcLocator ) + : FSMCallbackHolder<Algorithm>( name, pSvcLocator ) { + registerCallBack( StateMachine::INITIALIZE, []() { std::cout << "Callback properly called at INITIALIZE\n"; } ); + registerCallBack( StateMachine::START, []() { std::cout << "Callback properly called at START\n"; } ); + registerCallBack( StateMachine::STOP, []() { std::cout << "Callback properly called at STOP\n"; } ); + registerCallBack( StateMachine::FINALIZE, []() { std::cout << "Callback properly called at FINALIZE\n"; } ); + } + StatusCode execute( const EventContext& ) const override { + std::cout << "Executing\n"; + return StatusCode::SUCCESS; + } + }; + DECLARE_COMPONENT( FSMCallbackTestAlgo ); + +} // namespace Gaudi::TestSuite diff --git a/GaudiTestSuite/tests/qmtest/gauditestsuite.qms/callback.qmt b/GaudiTestSuite/tests/qmtest/gauditestsuite.qms/callback.qmt new file mode 100644 index 0000000000..1703df18a0 --- /dev/null +++ b/GaudiTestSuite/tests/qmtest/gauditestsuite.qms/callback.qmt @@ -0,0 +1,16 @@ +<?xml version="1.0" ?><!DOCTYPE extension PUBLIC '-//QM/2.3/Extension//EN' 'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'> +<!-- + (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations + + This software is distributed under the terms of the Apache version 2 licence, + copied verbatim in the file "LICENSE". + + In applying this licence, CERN does not waive the privileges and immunities + granted to it by virtue of its status as an Intergovernmental Organization + or submit itself to any jurisdiction. +--> +<extension class="GaudiTest.GaudiExeTest" kind="test"> + <argument name="program"><text>gaudirun.py</text></argument> + <argument name="args"><set><text>../../options/FSMCallbackTest.py</text></set></argument> + <argument name="reference"><text>refs/FSMCallbackTest.ref</text></argument> +</extension> diff --git a/GaudiTestSuite/tests/qmtest/refs/FSMCallbackTest.ref b/GaudiTestSuite/tests/qmtest/refs/FSMCallbackTest.ref new file mode 100644 index 0000000000..287071a430 --- /dev/null +++ b/GaudiTestSuite/tests/qmtest/refs/FSMCallbackTest.ref @@ -0,0 +1,26 @@ +# setting LC_ALL to "C" +# --> Including file '/home/sponce/master/Gaudi/GaudiTestSuite/options/CallBackTest.py' +# <-- End of file '/home/sponce/master/Gaudi/GaudiTestSuite/options/CallBackTest.py' +ApplicationMgr SUCCESS +==================================================================================================================================== + Welcome to ApplicationMgr (GaudiCoreSvc v38r2) + running on lblhcbpr11.cern.ch on Mon Jun 17 16:10:53 2024 +==================================================================================================================================== +ApplicationMgr INFO Application Manager Configured successfully +Callback properly called at INITIALIZE +EventLoopMgr WARNING Unable to locate service "EventSelector" +EventLoopMgr WARNING No events will be processed from external input. +ApplicationMgr INFO Application Manager Initialized successfully +Callback properly called at START +ApplicationMgr INFO Application Manager Started successfully +Executing +Executing +Executing +Executing +Executing +Callback properly called at STOP +ApplicationMgr INFO Application Manager Stopped successfully +Callback properly called at FINALIZE +EventLoopMgr INFO Histograms converted successfully according to request. +ApplicationMgr INFO Application Manager Finalized successfully +ApplicationMgr INFO Application Manager Terminated successfully -- GitLab