Skip to content
Snippets Groups Projects
Commit c75c005b authored by Gerhard Raven's avatar Gerhard Raven
Browse files

Simplify GaudiSequencer

- re-use Gaudi::Details::ostream_joiner
- avoid heap allocation
- avoid recursive variadic pack expansion
parent 8d59d401
No related branches found
No related tags found
1 merge request!483Simplify gaudisequencer
// Include files
#include <initializer_list>
#include <tuple>
// from Gaudi
#include "GaudiAlg/GaudiSequencer.h"
......@@ -11,41 +13,38 @@ namespace
bool isDefault( const std::string& s ) { return s.empty(); }
template <typename Container>
bool veto( const Container* props, const char* name )
{ // avoid changing properties explicitly present in the JOS...
return props &&
std::any_of( begin( *props ), end( *props ), [name]( const auto* prop ) { return prop->name() == name; } );
}
template <typename F, typename... Args>
void for_each_arg( F&& f, Args&&... args )
{
// the std::initializer_list only exists to provide a 'context' in which to
// expand the variadic pack
(void)std::initializer_list<int>{( f( std::forward<Args>( args ) ), 0 )...};
}
// utility class to populate some properties in the job options service
// for a given instance name in case those options are not explicitly
// set a-priori (effectively inheriting their values from the GaudiSequencer)
class populate_JobOptionsSvc_t
{
std::vector<std::unique_ptr<Gaudi::Details::PropertyBase>> m_props;
std::vector<std::string> m_props;
IJobOptionsSvc* m_jos;
std::string m_name;
template <typename T>
void process( T&& t )
{
static_assert( std::tuple_size<T>::value == 2, "Expecting an std::tuple key-value pair" );
using type = std::decay_t<std::tuple_element_t<1, T>>;
using prop_t = Gaudi::Property<type>;
if ( !isDefault( std::get<1>( t ) ) )
m_props.push_back( std::make_unique<prop_t>( std::get<0>( t ), std::get<1>( t ) ) );
}
template <typename T, typename... Args>
void process( T&& t, Args&&... args )
template <typename Properties, typename Key, typename Value>
void addPropertyToCatalogue( const Properties* props, const std::tuple<Key, Value>& arg )
{
process( std::forward<T>( t ) );
process( std::forward<Args>( args )... );
}
void check_veto()
{ // avoid changing properties expliclty present in the JOS...
const auto* props = m_jos->getProperties( m_name );
if ( !props ) return;
for ( const auto& i : *props ) {
auto j = std::find_if( std::begin( m_props ), std::end( m_props ),
[&i]( const auto& prop ) { return prop->name() == i->name(); } );
if ( j == std::end( m_props ) ) continue;
m_props.erase( j );
if ( m_props.empty() ) break; // done!
}
const auto& key = std::get<0>( arg );
const auto& value = std::get<1>( arg );
if ( isDefault( value ) || veto( props, key ) ) return;
m_jos->addPropertyToCatalogue( m_name, Gaudi::Property<std::decay_t<Value>>{key, value} ).ignore();
m_props.push_back( key );
}
public:
......@@ -53,30 +52,16 @@ namespace
populate_JobOptionsSvc_t( std::string name, IJobOptionsSvc* jos, Args&&... args )
: m_jos{jos}, m_name{std::move( name )}
{
process( std::forward<Args>( args )... );
if ( !m_props.empty() ) check_veto();
std::for_each( std::begin( m_props ), std::end( m_props ),
[&]( const auto& i ) { m_jos->addPropertyToCatalogue( m_name, *i ).ignore(); } );
const auto* props = m_jos->getProperties( m_name );
for_each_arg( [&]( auto&& arg ) { this->addPropertyToCatalogue( props, std::forward<decltype( arg )>( arg ) ); },
std::forward<Args>( args )... );
}
~populate_JobOptionsSvc_t()
{
std::for_each( std::begin( m_props ), std::end( m_props ),
[&]( const auto& i ) { m_jos->removePropertyFromCatalogue( m_name, i->name() ).ignore(); } );
std::for_each( begin( m_props ), end( m_props ),
[&]( const std::string& key ) { m_jos->removePropertyFromCatalogue( m_name, key ).ignore(); } );
}
};
template <typename Stream, typename Container, typename Separator, typename Transform>
Stream& ostream_joiner( Stream& os, const Container& c, Separator sep, Transform trans )
{
auto first = std::begin( c );
auto last = std::end( c );
if ( first != last ) {
os << trans( *first );
++first;
}
for ( ; first != last; ++first ) os << sep << trans( *first );
return os;
}
}
//-----------------------------------------------------------------------------
......@@ -203,7 +188,6 @@ StatusCode GaudiSequencer::execute()
//=============================================================================
StatusCode GaudiSequencer::finalize()
{
if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Finalize" << endmsg;
return GaudiAlgorithm::finalize();
}
......@@ -213,7 +197,6 @@ StatusCode GaudiSequencer::finalize()
//=========================================================================
StatusCode GaudiSequencer::beginRun()
{
if ( !isEnabled() ) return StatusCode::SUCCESS;
if ( msgLevel( MSG::DEBUG ) ) debug() << "==> beginRun" << endmsg;
return StatusCode::SUCCESS;
......@@ -224,7 +207,6 @@ StatusCode GaudiSequencer::beginRun()
//=========================================================================
StatusCode GaudiSequencer::endRun()
{
if ( !isEnabled() ) return StatusCode::SUCCESS;
if ( msgLevel( MSG::DEBUG ) ) debug() << "==> endRun" << endmsg;
return StatusCode::SUCCESS;
......@@ -235,7 +217,6 @@ StatusCode GaudiSequencer::endRun()
//=========================================================================
StatusCode GaudiSequencer::decodeNames()
{
StatusCode final = StatusCode::SUCCESS;
m_entries.clear();
......@@ -273,19 +254,15 @@ StatusCode GaudiSequencer::decodeNames()
// propagate the sub-algorithm into own state.
if ( result.isSuccess() && Gaudi::StateMachine::INITIALIZED <= FSMState() && myIAlg &&
Gaudi::StateMachine::INITIALIZED > myIAlg->FSMState() ) {
StatusCode sc = myIAlg->sysInitialize();
if ( sc.isFailure() ) {
result = sc;
}
StatusCode sc = myIAlg->sysInitialize();
if ( sc.isFailure() ) result = sc;
}
// propagate the sub-algorithm into own state.
if ( result.isSuccess() && Gaudi::StateMachine::RUNNING <= FSMState() && myIAlg &&
Gaudi::StateMachine::RUNNING > myIAlg->FSMState() ) {
StatusCode sc = myIAlg->sysStart();
if ( sc.isFailure() ) {
result = sc;
}
StatusCode sc = myIAlg->sysStart();
if ( sc.isFailure() ) result = sc;
}
//== Is it an Algorithm ? Strange test...
......@@ -311,11 +288,12 @@ StatusCode GaudiSequencer::decodeNames()
MsgStream& msg = info();
if ( m_modeOR ) msg << "OR ";
msg << "Member list: ";
ostream_joiner( msg, m_entries, ", ", []( const AlgorithmEntry& e ) {
Algorithm* alg = e.algorithm();
std::string typ = System::typeinfoName( typeid( *alg ) );
return ( alg->name() == typ ) ? alg->name() : ( typ + "/" + alg->name() );
} );
GaudiUtils::details::ostream_joiner(
msg, m_entries, ", ", []( auto& os, const AlgorithmEntry& e ) -> decltype( auto ) {
Algorithm* alg = e.algorithm();
std::string typ = System::typeinfoName( typeid( *alg ) );
return os << ( alg->name() == typ ? alg->name() : ( typ + "/" + alg->name() ) );
} );
if ( !isDefault( context() ) ) msg << ", with context '" << context() << "'";
if ( !isDefault( rootInTES() ) ) msg << ", with rootInTES '" << rootInTES() << "'";
msg << endmsg;
......@@ -329,15 +307,11 @@ StatusCode GaudiSequencer::decodeNames()
void GaudiSequencer::membershipHandler( Gaudi::Details::PropertyBase& /* p */ )
{
// no action for not-yet initialized sequencer
if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) {
return;
} // RETURN
if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) return; // RETURN
decodeNames().ignore();
if ( !m_measureTime ) {
return;
} // RETURN
if ( !m_measureTime ) return; // RETURN
// add the entries into timer table:
......@@ -367,14 +341,12 @@ std::ostream& GaudiSequencer::toControlFlowExpression( std::ostream& os ) const
if ( m_entries.size() > 1 ) os << "seq(";
const auto op = m_modeOR ? " | " : " & ";
const auto first = begin( m_entries );
const auto last = end( m_entries );
auto iterator = first;
while ( iterator != last ) {
const auto first = begin( m_entries );
for ( auto iterator = first; iterator != last; ++iterator ) {
if ( iterator != first ) os << op;
if ( iterator->reverse() ) os << "~";
iterator->algorithm()->toControlFlowExpression( os );
++iterator;
}
if ( m_entries.size() > 1 ) os << ")";
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment