ATLAS Offline Software
GaudiComponentVisitor.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 #include "CxxUtils/checker_macros.h"
5 #include "GaudiKernel/AlgTool.h"
6 #include "Gaudi/Sequence.h"
7 
8 namespace xGaudi {
9 
10  namespace {
11  template <class T_Component>
12  void reverseAppend( const std::vector<T_Component*>& src,
13  std::vector<T_Component*>& dest,
14  const std::regex& reject_filter,
15  bool use_filter ) {
16  dest.reserve( dest.size() + src.size() );
17  std::copy_if( src.rbegin(), src.rend(), std::back_inserter( dest ), [&]( const auto& i ) {
18  return !use_filter || !std::regex_match( i->name(), reject_filter );
19  } ); // @TODO include type ?
20  }
21  } // namespace
22 
23  template <class T_Component, class T_TestVisited>
24  void ComponentVisitor<T_Component,T_TestVisited>::recursiveVisit( const std::vector<T_Component*>& components,
25  ComponentVisitor<T_Component, T_TestVisited>::IVisitor const& visitor,
26  const std::regex& reject_filter,
27  T_TestVisited &visited) {
28  bool use_filter = ( &reject_filter != &ComponentVisitorBase::s_noFilter ) &&
29  ( !std::regex_match( "", reject_filter ) ); // @TODO remove empty string match-test ?
30  std::vector<T_Component*> stack;
31  // reverse tool lost to process tools in given order
32  reverseAppend( components, stack, reject_filter, use_filter );
33 
34  while ( !stack.empty() ) {
35  auto* a_tool = stack.back();
36  stack.pop_back();
37  if ( a_tool ) {
38  // keep track of tools which have been visited to prevent infinite loops in case of circular tool dependencies.
39  if ( visited.insert( a_tool ).second ) {
40  visitor.visit( a_tool );
41  // also visit all child tools
42  if (const std::vector<T_Component *> *childs( getChilds(a_tool)); childs ) {
43  reverseAppend( *childs, stack, reject_filter, use_filter );
44  }
45  }
46  // @TODO warn about cicular tool dependencies ?
47  }
48  }
49  }
50 
51  template <>
52  inline std::vector<IAlgTool *> *ComponentVisitor<IAlgTool>::getChilds(IAlgTool *a_tool) {
53  if ( auto* tool_impl = dynamic_cast<AlgTool*>( a_tool ); tool_impl ) {
54  std::vector<IAlgTool *> &tools ATLAS_THREAD_SAFE = const_cast< std::vector<IAlgTool *> &>(const_cast<const AlgTool *>(tool_impl)->tools());
55  return &tools;
56  }
57  else {
58  return nullptr;
59  }
60  }
61 
62  template <>
63  inline std::vector<Gaudi::Algorithm *> *ComponentVisitor<Gaudi::Algorithm, NoVisitTester>::getChilds(Gaudi::Algorithm *an_alg) {
64  if (Gaudi::Sequence *seq=dynamic_cast<Gaudi::Sequence *>(an_alg); seq) {
65  return seq->subAlgorithms( );
66  }
67  else {
68  return nullptr;
69  }
70  }
71 }