diff --git a/GaudiKernel/include/Gaudi/FSMCallbackHolder.h b/GaudiKernel/include/Gaudi/FSMCallbackHolder.h new file mode 100644 index 0000000000000000000000000000000000000000..e7ada4ff607ee8522501d1d01f40b6b3f78b3580 --- /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 0000000000000000000000000000000000000000..bb7072419650578273eae2bc61bf3dec387a428f --- /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 4a84a4fd6bf4117f473dc90e57279542292c60fa..0434723398ce6a608a056bffe6018fbf27b33fa6 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 0000000000000000000000000000000000000000..26e303452b84c5dd873754a76c91edfe4f792d7a --- /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 0000000000000000000000000000000000000000..ade8fcee638b073faef6074d20e53d723d537a0a --- /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 0000000000000000000000000000000000000000..1703df18a0f66a04aefe04a0682443921dbc817b --- /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 0000000000000000000000000000000000000000..287071a430594195e8dc4315bf3d6afad16a8de0 --- /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