The Gaudi Framework  v29r0 (ff2e7097)
Sequencer.cpp
Go to the documentation of this file.
1 // Sequencer class
2 // Implements:
3 // 1) Common functionality of IInterface
4 // 2) Default behavior for the IAlgorithm
5 
6 #include "GaudiAlg/Sequencer.h"
7 
8 #include "GaudiKernel/Chrono.h"
12 #include "GaudiKernel/Stat.h"
13 
14 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
15 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
16 
20 Sequencer::Sequencer( const std::string& name, ISvcLocator* pSvcLocator ) : Algorithm( name, pSvcLocator )
21 {
22  // Associate action handlers with the "Members" and "BranchMembers" properties
23  m_names.declareUpdateHandler( [this]( Gaudi::Details::PropertyBase& ) {
24  if ( isInitialized() ) decodeMemberNames().ignore();
25  } );
26  m_branchNames.declareUpdateHandler( [this]( Gaudi::Details::PropertyBase& ) {
27  if ( isInitialized() ) decodeBranchMemberNames().ignore();
28  } );
29 }
30 
32 {
34 
35  result = decodeMemberNames();
36  if ( result.isFailure() ) {
37  error() << "Unable to configure one or more sequencer members " << endmsg;
38  return result;
39  }
40  result = decodeBranchMemberNames();
41  if ( result.isFailure() ) {
42  error() << "Unable to configure one or more branch members " << endmsg;
43  return result;
44  }
45 
46  // Loop over all sub-algorithms
47  for ( auto& alg : *subAlgorithms() ) {
48  result = alg->sysInitialize();
49  if ( result.isFailure() ) {
50  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
51  return result;
52  }
53  }
54 
55  // Loop over all branches
56  for ( auto& alg : branchAlgorithms() ) {
57  result = alg->sysInitialize();
58  if ( result.isFailure() ) {
59  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
60  return result;
61  }
62  }
63 
64  return result;
65 }
66 
68 {
69  // Bypass the loop if this sequencer is disabled
70  if ( isEnabled() ) {
71 
72  // Loop over all members calling their reinitialize functions
73  // if they are not disabled.
74  for ( auto& alg : *subAlgorithms() ) {
75  if ( alg->isEnabled() ) alg->reinitialize().ignore();
76  }
77  // Loop over all branch members calling their reinitialize functions
78  // if they are not disabled.
79  for ( auto& alg : branchAlgorithms() ) {
80  if ( alg->isEnabled() ) {
81  alg->reinitialize().ignore();
82  }
83  }
84  }
85  return StatusCode::SUCCESS;
86 }
87 
89 {
91  ON_DEBUG debug() << name() << " Sequencer::execute( )" << endmsg;
92 
93  // Bypass the loop if this sequencer is disabled or has already been executed
94  if ( isEnabled() && !isExecuted() ) {
95  Algorithm* lastAlgorithm;
96  result = execute( *subAlgorithms(), m_isInverted, lastAlgorithm );
97  if ( result.isSuccess() ) {
98  bool passed = filterPassed();
99  if ( !passed && !isStopOverride() ) {
100 
101  // Filter failed and stop override not set. Execute the
102  // branch if there is one associated with the filter
103  // algorithm that failed. Note that the first member on
104  // the branch is the failing algorithm and so should
105  // be skipped.
106  const auto& theAlgs = branchAlgorithms();
107  if ( !theAlgs.empty() ) {
108  Algorithm* branchAlgorithm = theAlgs[0];
109  if ( lastAlgorithm == branchAlgorithm ) {
110 
111  // Branch specified - Loop over branch members
112  result = execute( branchAlgorithms(), m_isBranchInverted, lastAlgorithm, 1 );
113  if ( result.isSuccess() ) {
114 
115  // The final filter passed state will be set true if either
116  // of the main or branches passed, otherwise false.
117 
118  // Save the branch filter passed state.
120  }
121  }
122  }
123  }
124  }
125 
126  // Prevent multiple executions of this sequencer for the current event
127  setExecuted( true );
128  }
129  return result;
130 }
131 
133 {
134  // Loop over all branch members calling their finalize functions
135  // if they are not disabled. Note that the Algorithm::sysFinalize
136  // function already does this for the main members.
137  for ( auto& alg : branchAlgorithms() ) {
138  if ( alg->sysFinalize().isFailure() ) {
139  error() << "Unable to finalize Algorithm " << alg->name() << endmsg;
140  }
141  }
142  return StatusCode::SUCCESS;
143 }
144 
146 {
148 
149  // Loop over all sub-algorithms
150  for ( auto& alg : *subAlgorithms() ) {
151  result = alg->sysStart();
152  if ( result.isFailure() ) {
153  error() << "Unable to start Algorithm " << alg->name() << endmsg;
154  return result;
155  }
156  }
157 
158  // Loop over all branches
159  for ( auto& alg : branchAlgorithms() ) {
160  result = alg->sysStart();
161  if ( result.isFailure() ) {
162  error() << "Unable to start Algorithm " << alg->name() << endmsg;
163  return result;
164  }
165  }
166 
167  return result;
168 }
169 
171 {
172  // Loop over all branch members calling their finalize functions
173  // if they are not disabled.
174 
175  for ( auto& alg : *subAlgorithms() ) {
176  if ( alg->sysStop().isFailure() ) {
177  error() << "Unable to stop Algorithm " << alg->name() << endmsg;
178  }
179  }
180 
181  for ( auto& alg : branchAlgorithms() ) {
182  if ( alg->sysStop().isFailure() ) {
183  error() << "Unable to stop Algorithm " << alg->name() << endmsg;
184  }
185  }
186  return StatusCode::SUCCESS;
187 }
188 
190 {
192 
193  // Bypass the loop if this sequencer is disabled
194  if ( isEnabled() ) {
195 
196  // Loop over all members calling their sysInitialize functions
197  // if they are not disabled. Note that the Algoriithm::sysInitialize
198  // function protects this from affecting Algorithms that have already
199  // been initialized.
200  for ( auto& alg : *subAlgorithms() ) {
201  result = alg->sysInitialize();
202  if ( result.isFailure() ) {
203  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
204  break;
205  }
206  result = alg->sysStart();
207  if ( result.isFailure() ) {
208  error() << "Unable to start Algorithm " << alg->name() << endmsg;
209  break;
210  }
211  }
212 
213  // Loop over all members calling their beginRun functions
214  // if they are not disabled.
215  for ( auto& alg : *subAlgorithms() ) {
216  if ( !alg->isEnabled() ) {
217  alg->beginRun().ignore();
218  }
219  }
220 
221  // Loop over all branch members calling their sysInitialize functions
222  // if they are not disabled. Note that the Algoriithm::sysInitialize
223  // function protects this from affecting Algorithms that have already
224  // been initialized.
225  for ( auto& alg : branchAlgorithms() ) {
226  result = alg->sysInitialize();
227  if ( result.isFailure() ) {
228  error() << "Unable to initialize Algorithm " << alg->name() << endmsg;
229  break;
230  }
231  result = alg->sysStart();
232  if ( result.isFailure() ) {
233  error() << "Unable to start Algorithm " << alg->name() << endmsg;
234  break;
235  }
236  }
237 
238  // Loop over all branch members calling their beginRun functions
239  // if they are not disabled.
240  for ( auto& alg : branchAlgorithms() ) {
241  if ( !alg->isEnabled() ) {
242  alg->beginRun().ignore();
243  }
244  }
245  }
246  return StatusCode::SUCCESS;
247 }
248 
250 {
251  // Bypass the loop if this sequencer is disabled
252  if ( isEnabled() ) {
253 
254  // Loop over all members calling their endRun functions
255  // if they are not disabled.
256  for ( auto& alg : *subAlgorithms() ) {
257  if ( !alg->isEnabled() ) alg->endRun().ignore();
258  }
259  // Loop over all branch members calling their endRun functions
260  // if they are not disabled.
261  for ( auto& alg : branchAlgorithms() ) {
262  if ( !alg->isEnabled() ) alg->endRun().ignore();
263  }
264  }
265  return StatusCode::SUCCESS;
266 }
267 
269 {
271 
272  // Loop over all members calling their resetExecuted functions
273  // if they are not disabled.
274  for ( auto& alg : *subAlgorithms() ) alg->resetExecuted();
275 
276  // Loop over all branch members calling their resetExecuted functions
277  // if they are not disabled.
278  for ( auto& alg : branchAlgorithms() ) alg->resetExecuted();
279 
280  // Reset the branch filter passed flag
281  m_branchFilterPassed = false;
282 }
283 
285 
287 {
289  return StatusCode::SUCCESS;
290 }
291 
292 bool Sequencer::isStopOverride() const { return m_stopOverride.value(); }
293 
294 StatusCode Sequencer::append( Algorithm* pAlgorithm ) { return append( pAlgorithm, *subAlgorithms() ); }
295 
296 StatusCode Sequencer::appendToBranch( Algorithm* pAlgorithm ) { return append( pAlgorithm, branchAlgorithms() ); }
297 
299 {
300  return createAndAppend( type, name, pAlgorithm, *subAlgorithms() );
301 }
302 
304  Algorithm*& pAlgorithm )
305 {
306  return createAndAppend( type, name, pAlgorithm, branchAlgorithms() );
307 }
308 
309 StatusCode Sequencer::remove( Algorithm* pAlgorithm ) { return remove( pAlgorithm->name() ); }
310 
311 StatusCode Sequencer::remove( const std::string& algname ) { return remove( algname, *subAlgorithms() ); }
312 
313 StatusCode Sequencer::removeFromBranch( Algorithm* pAlgorithm ) { return removeFromBranch( pAlgorithm->name() ); }
314 
315 StatusCode Sequencer::removeFromBranch( const std::string& algname ) { return remove( algname, branchAlgorithms() ); }
316 
318 
320 
322 {
323  // Decode the membership list
325 }
326 
328 {
329  // Decode the branch membership list
331 }
332 
338 {
339  // Check that the specified algorithm doesn't already exist in the membership list
340  if ( std::find( std::begin( theAlgs ), std::end( theAlgs ), pAlgorithm ) != std::end( theAlgs ) ) {
341  return StatusCode::FAILURE;
342  }
343  theAlgs.push_back( pAlgorithm );
344  pAlgorithm->addRef();
345  return StatusCode::SUCCESS;
346 }
347 
349  std::vector<Algorithm*>& theAlgs )
350 {
351  auto theAlgMgr = serviceLocator()->service<IAlgManager>( "ApplicationMgr" );
352  if ( !theAlgMgr ) return StatusCode::FAILURE;
353 
354  IAlgorithm* tmp;
355  StatusCode result = theAlgMgr->createAlgorithm( type, algName, tmp );
356  if ( result.isSuccess() ) {
357  try {
358  pAlgorithm = dynamic_cast<Algorithm*>( tmp );
359  theAlgs.push_back( pAlgorithm );
360  } catch ( ... ) {
361  error() << "Unable to create Algorithm " << algName << endmsg;
362  result = StatusCode::FAILURE;
363  }
364  }
365 
366  return result;
367 }
368 
370  std::vector<Algorithm*>& theAlgs, std::vector<bool>& theLogic )
371 {
372  StatusCode result;
373  auto theAlgMgr = serviceLocator()->service<IAlgManager>( "ApplicationMgr" );
374  if ( theAlgMgr ) {
375  // Clear the existing list of algorithms
376  theAlgs.clear();
377 
378  // Build the list of member algorithms from the contents of the
379  // theNames list.
380  for ( const auto& n : theNames.value() ) {
381 
382  // Parse the name for a syntax of the form:
383  //
384  // <type>/<name>
385  //
386  // Where <name> is the algorithm instance name, and <type> is the
387  // algorithm class type (being a subclass of Algorithm).
389  std::string theName = typeName.name();
390  std::string theType = typeName.type();
391 
392  // Parse the name for a syntax of the form:
393  //
394  // <name>:invert
395  //
396  // Where <name> is the algorithm instance name and ":invert"
397  // indicates that the filter passed logic is inverted.
398  bool isInverted = false;
399  std::string::size_type invert = theName.find_first_of( ":" );
400  // Skip all occurrences of "::" (allow namespaces)
401  while ( std::string::npos != invert && invert < ( theName.size() - 1 ) && theName[invert + 1] == ':' )
402  invert = theName.find_first_of( ":", invert + 2 );
403  if ( std::string::npos != invert ) {
404  if ( theName == theType ) {
405  // This means that we got something like "Type:invert",
406  // so we have to strip the ":invert" from the type too.
407  theType = theType.substr( 0, invert );
408  }
409  theName = theName.substr( 0, invert );
410  isInverted = true;
411  }
412  // Check whether the supplied name corresponds to an existing
413  // Algorithm object.
414  SmartIF<IAlgorithm>& theIAlg = theAlgMgr->algorithm( theName, false );
415  Algorithm* theAlgorithm = nullptr;
417  if ( theIAlg ) {
418  try {
419  theAlgorithm = dynamic_cast<Algorithm*>( theIAlg.get() );
420  } catch ( ... ) {
421  warning() << theName << " is not an Algorithm - Failed dynamic cast" << endmsg;
422  theAlgorithm = nullptr; // release
423  }
424  }
425  if ( theAlgorithm ) {
426 
427  // The specified Algorithm already exists - just append it to the membership list.
428  status = append( theAlgorithm, theAlgs );
429  if ( status.isSuccess() ) {
430  ON_DEBUG debug() << theName << " already exists - appended to member list" << endmsg;
431  } else {
432  warning() << theName << " already exists - append failed!!!" << endmsg;
433  result = StatusCode::FAILURE;
434  }
435  } else {
436 
437  // The specified name doesn't exist - create a new object of the specified type
438  // and append it to the membership list.
439  status = createAndAppend( theType, theName, theAlgorithm, theAlgs );
440  if ( status.isSuccess() ) {
441  ON_DEBUG debug() << theName << " doesn't exist - created and appended to member list" << endmsg;
442  } else {
443  warning() << theName << " doesn't exist - creation failed!!!" << endmsg;
444  result = StatusCode::FAILURE;
445  }
446  }
447  if ( status.isSuccess() ) theLogic.push_back( isInverted );
448  }
449  }
450  // Print membership list
451  if ( result.isSuccess() && theAlgs.size() != 0 ) {
452  info() << "Member list: ";
453  auto ai = theAlgs.begin();
454  auto li = theLogic.begin();
455  for ( ; ai != theAlgs.end(); ++ai, ++li ) {
456 
457  if ( ai != theAlgs.begin() ) info() << ", ";
458  auto alg = *ai;
459  if ( alg->name() == System::typeinfoName( typeid( *alg ) ) )
460  info() << alg->name();
461  else
462  info() << System::typeinfoName( typeid( *alg ) ) << "/" << alg->name();
463 
464  if ( *li ) info() << ":invert";
465  }
466  info() << endmsg;
467  }
468  return result;
469 }
470 
472  Algorithm*& lastAlgorithm, unsigned int first )
473 {
475 
476  // Loop over all algorithms calling their execute functions if they
477  // are (a) not disabled, and (b) aren't already executed. Note that
478  // in the latter case the filter state is still examined. Terminate
479  // the loop if an algorithm indicates that it's filter didn't pass.
480  unsigned int size = theAlgs.size();
481  for ( unsigned int i = first; i < size; i++ ) {
482  lastAlgorithm = theAlgs[i];
483  result = executeMember( lastAlgorithm );
484  if ( result.isSuccess() ) {
485 
486  // Take the filter passed status of this algorithm as my own status.
487  // Note that we take into account inverted logic.
488  bool passed = lastAlgorithm->filterPassed();
489  bool isInverted = theLogic[i];
490  if ( isInverted ) passed = !passed;
491  setFilterPassed( passed );
492 
493  // The behaviour when the filter fails depends on the StopOverride property.
494  // The default action is to stop processing, but this default can be
495  // overridden by setting the "StopOverride" property to true.
496  if ( !isStopOverride() ) {
497  if ( !passed ) break;
498  }
499  } else {
500  break;
501  }
502  }
503  return result;
504 }
505 
507 {
509  if ( theAlgorithm->isEnabled() ) {
510  if ( !theAlgorithm->isExecuted() ) {
511  result = theAlgorithm->sysExecute( getContext() );
512 
513  // Set the executed state of the algorithm.
514  // I think this should be done by the algorithm itself, but just in case...
515  theAlgorithm->setExecuted( true );
516  }
517  }
518  return result;
519 }
520 
522 {
524 
525  // Test that the algorithm exists in the member list
526  for ( auto& alg : theAlgs ) {
527  if ( alg->name() == algname ) {
528 
529  // Algorithm with specified name exists in the algorithm list - remove it
530  // THIS ISN'T IMPLEMENTED YET!!!!
531  info() << "Sequencer::remove( ) isn't implemented yet!!!!!" << endmsg;
532  result = StatusCode::SUCCESS;
533  break;
534  }
535  }
536  return result;
537 }
538 
540 {
541  auto& theAlgs = *subAlgorithms();
542  if ( theAlgs.empty() ) return os << "CFTrue";
543 
544  os << "seq(";
545  const auto algs_count = theAlgs.size();
546  const auto op = isStopOverride() ? " >> " : " & ";
547  size_t i = 0;
548  while ( i < algs_count ) {
549  if ( i ) os << op;
550  if ( m_isInverted[i] ) os << "~";
551  theAlgs[i]->toControlFlowExpression( os );
552  ++i;
553  }
554  return os << ")";
555 }
void resetExecuted() override
Reset the executed state of the Algorithm for the duration of the current event.
Definition: Algorithm.cpp:754
virtual bool isStopOverride() const
Has the StopOverride mode been set?
Definition: Sequencer.cpp:292
StatusCode append(Algorithm *pAlgorithm)
Append an algorithm to the sequencer.
Definition: Sequencer.cpp:294
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:731
void setFilterPassed(bool state) const override
Set the filter passed flag to the specified state.
Definition: Algorithm.cpp:768
StatusCode remove(Algorithm *pAlgorithm)
Remove the specified algorithm from the sequencer.
Definition: Sequencer.cpp:309
Implementation of property with value of concrete type.
Definition: Property.h:319
StatusCode removeFromBranch(Algorithm *pAlgorithm)
Definition: Sequencer.cpp:313
bool isExecuted() const override
Has this algorithm been executed since the last reset?
Definition: Algorithm.cpp:741
Gaudi::Property< std::vector< std::string > > m_branchNames
Definition: Sequencer.h:233
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:329
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:75
Sequencer(const std::string &name, ISvcLocator *svcloc)
Constructor(s)
Definition: Sequencer.cpp:20
The IAlgManager is the interface implemented by the Algorithm Factory in the Application Manager to s...
Definition: IAlgManager.h:27
virtual bool branchFilterPassed() const
Was the branch filter passed for the last event?
Definition: Sequencer.cpp:284
StatusCode stop() override
Sequencer finalization.
Definition: Sequencer.cpp:170
bool m_branchFilterPassed
Definition: Sequencer.h:240
T end(T...args)
StatusCode reinitialize() override
Sequencer Reinitialization.
Definition: Sequencer.cpp:67
StatusCode beginRun() override
Sequencer beginRun.
Definition: Sequencer.cpp:189
const std::vector< Algorithm * > & branchAlgorithms() const
List of branch algorithms.
Definition: Sequencer.cpp:317
StatusCode executeMember(Algorithm *theAlgorithm)
Execute member algorithm.
Definition: Sequencer.cpp:506
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
StatusCode decodeBranchMemberNames()
Decode branch member name list.
Definition: Sequencer.cpp:327
STL class.
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:82
virtual StatusCode setBranchFilterPassed(bool state)
Set the branch filter passed flag for the last event.
Definition: Sequencer.cpp:286
Gaudi::Property< bool > m_stopOverride
Definition: Sequencer.h:234
StatusCode service(const Gaudi::Utils::TypeNameString &name, T *&svc, bool createIf=true)
Templated method to access a service by name.
Definition: ISvcLocator.h:79
T push_back(T...args)
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
bool isEnabled() const override
Is this algorithm enabled or disabled?
Definition: Algorithm.cpp:760
Helper class to parse a string of format "type/name".
StatusCode execute() override
The actions to be performed by the sequencer on an event.
Definition: Sequencer.cpp:88
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
StatusCode decodeMemberNames()
Decode Member Name list.
Definition: Sequencer.cpp:321
StatusCode createAndAppendToBranch(const std::string &type, const std::string &name, Algorithm *&pAlgorithm)
Create a algorithm and append it to the sequencer branch.
Definition: Sequencer.cpp:303
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:28
const EventContext & getContext() const override
get the context
Definition: Algorithm.h:436
Gaudi::Property< std::vector< std::string > > m_names
Definition: Sequencer.h:232
T find_first_of(T...args)
std::ostream & toControlFlowExpression(std::ostream &os) const override
Produce string represention of the control flow expression.
Definition: Sequencer.cpp:539
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Definition: Property.h:32
T clear(T...args)
The IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:28
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Algorithm.cpp:809
const std::vector< Algorithm * > * subAlgorithms() const
List of sub-algorithms. Returns a pointer to a vector of (sub) Algorithms.
Definition: Algorithm.cpp:776
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:78
T find(T...args)
T size(T...args)
std::vector< Algorithm * > m_branchAlgs
Definition: Sequencer.h:237
#define ON_DEBUG
Definition: Sequencer.cpp:14
StatusCode endRun() override
Sequencer endRun.
Definition: Sequencer.cpp:249
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
std::vector< bool > m_isInverted
Definition: Sequencer.h:236
StatusCode createAndAppend(const std::string &type, const std::string &name, Algorithm *&pAlgorithm)
Create a algorithm and append it to the sequencer.
Definition: Sequencer.cpp:298
T begin(T...args)
bool isInitialized() const override
Has the Algorithm already been initialized?
Definition: Algorithm.h:497
const std::string & type() const
bool filterPassed() const override
Did this algorithm pass or fail its filter criterion for the last event?
Definition: Algorithm.cpp:762
StatusCode appendToBranch(Algorithm *pAlgorithm)
Append an algorithm to the sequencer branch.
Definition: Sequencer.cpp:296
void setExecuted(bool state) const override
Set the executed flag to the specified state.
Definition: Algorithm.cpp:747
T substr(T...args)
StatusCode decodeNames(Gaudi::Property< std::vector< std::string >> &theNames, std::vector< Algorithm * > &theAlgs, std::vector< bool > &theLogic)
Decode algorithm names, creating or appending algorithms as appropriate.
Definition: Sequencer.cpp:369
StatusCode finalize() override
Sequencer finalization.
Definition: Sequencer.cpp:132
StatusCode initialize() override
Initialization of a sequencer.
Definition: Sequencer.cpp:31
const std::string & name() const
void ignore() const
Definition: StatusCode.h:109
std::string typeName(const std::type_info &typ)
Definition: Dictionary.cpp:23
const std::string & type() const override
The type of the algorithm object.
Definition: Algorithm.h:166
STL class.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
void resetExecuted() override
Reset the Sequencer executed state for the current event.
Definition: Sequencer.cpp:268
StatusCode sysExecute(const EventContext &ctx) override
The actions to be performed by the algorithm on an event.
Definition: Algorithm.cpp:502
std::vector< bool > m_isBranchInverted
Definition: Sequencer.h:238
StatusCode start() override
Sequencer finalization.
Definition: Sequencer.cpp:145