Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v38r0 (2143aa4c)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ToolSvc.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 // Include Files
12 #include "ToolSvc.h"
13 #include "GaudiKernel/AlgTool.h"
15 #include "GaudiKernel/IAlgorithm.h"
18 #include "GaudiKernel/MsgStream.h"
19 #include "GaudiKernel/Service.h"
20 #include "boost/algorithm/string/erase.hpp"
21 #include "boost/algorithm/string/predicate.hpp"
22 #include "boost/circular_buffer.hpp"
23 #include <algorithm>
24 #include <cassert>
25 #include <functional>
26 #include <map>
27 #include <numeric>
28 #include <string>
29 namespace ba = boost::algorithm;
30 
31 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
32 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
33 
34 namespace {
35  //------------------------------------------------------------------------------
36  template <typename C>
37  unsigned long totalRefCount( const C& toolList )
38  //------------------------------------------------------------------------------
39  {
40  return std::accumulate( std::begin( toolList ), std::end( toolList ), 0ul,
41  [&]( unsigned long count, const IAlgTool* tool ) { return count + tool->refCount(); } );
42  }
43 
45  template <typename C>
46  void remove( C& c, typename C::const_reference i ) {
47  c.erase( std::remove( std::begin( c ), std::end( c ), i ), std::end( c ) );
48  }
49 
51  auto range = c.equal_range( tool->name() );
52  auto itm = std::find_if( range.first, range.second, [&]( auto const& p ) { return p.second == tool; } );
53  if ( itm == range.second ) {
54  throw GaudiException( "Inconsistency between tool vector and tool map", __PRETTY_FUNCTION__,
56  }
57  c.erase( itm );
58  }
59 
60 } // namespace
61 
62 // Instantiation of a static factory class used by clients to create
63 // instances of this service
65 
66 //------------------------------------------------------------------------------
68  // tell the remaining observers that we're gone, and forget about unregistering..
69  std::for_each( std::begin( m_observers ), std::end( m_observers ),
70  [&]( IToolSvc::Observer* obs ) { obs->setUnregister( {} ); } );
71 }
72 
73 //------------------------------------------------------------------------------
75 //------------------------------------------------------------------------------
76 {
77  // Finalize and delete all left-over tools. Normally all tools created with
78  // ToolSvc are left over, since ToolSvc holds a refCount (via AlgTool ctor).
79  // Several cases need to be covered:
80  // 1) Simple dependencies: no circular dependencies between tools,
81  // and tools not using other tools
82  // 2) Tools-using-tools (but no circular dependencies)
83  // a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
84  // b) release() is called in the tool destructor (e.g. via ToolHandle)
85  // 3) Circular dependencies between tools
86  // a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
87  // b) release() is called in the tool destructor (e.g. via ToolHandle)
88  // 4) In addition to each of the above cases, refCounting of a particular tool
89  // might not have been done correctly in the code. Typically release()
90  // is not called, so we are left with a too high refCount.
91  // What to do with those, and how to avoid a crash while handling them...
92 
101  info() << "Removing all tools created by ToolSvc" << endmsg;
102 
103  // Print out list of tools
104  ON_DEBUG {
105  auto& log = debug();
106  log << " Tool List : ";
107  for ( const auto& iTool : m_instancesTools ) { log << iTool->name() << ":" << iTool->refCount() << " "; }
108  log << endmsg;
109  }
110 
111  //
112  // first pass: Finalize all tools (but don't delete them)
113  //
126  boost::circular_buffer<IAlgTool*> finalizedTools( m_instancesTools.size() ); // list of tools that have been finalized
127  bool fail( false );
128  size_t toolCount = m_instancesTools.size();
129  unsigned long startRefCount = 0;
130  unsigned long endRefCount = totalToolRefCount();
131  unsigned long startMinRefCount = 0;
132  unsigned long endMinRefCount = minimumToolRefCount();
133  while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
134  ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
135  debug() << toolCount << " tools left to finalize. Summed refCounts: " << endRefCount << endmsg;
136  debug() << "Will finalize tools with refCount <= " << endMinRefCount << endmsg;
137  }
138  startMinRefCount = endMinRefCount;
139  startRefCount = endRefCount;
140  unsigned long maxLoop = toolCount + 1;
141  while ( --maxLoop > 0 && !m_instancesTools.empty() ) {
142  IAlgTool* pTool = m_instancesTools.back();
143  // removing tool from list makes ToolSvc::releaseTool( IAlgTool* ) a noop
145  unsigned long count = pTool->refCount();
146  // cache tool name
147  const std::string& toolName = pTool->name();
148  if ( count <= startMinRefCount ) {
149  ON_DEBUG debug() << " Performing finalization of " << toolName << " (refCount " << count << ")" << endmsg;
150  // finalize of one tool may trigger a release of another tool
151  // pTool->sysFinalize().ignore();
152  if ( !finalizeTool( pTool ).isSuccess() ) {
153  warning() << " FAILURE finalizing " << toolName << endmsg;
154  fail = true;
155  }
156  // postpone deletion
157  finalizedTools.push_back( pTool );
158  } else {
159  // Place back at the front of the list to try again later
160  // ToolSvc::releaseTool( IAlgTool* ) remains active for this tool
161  ON_DEBUG debug() << " Delaying finalization of " << toolName << " (refCount " << count << ")" << endmsg;
163  }
164  } // end of inner loop
165  toolCount = m_instancesTools.size();
166  endRefCount = totalToolRefCount();
167  endMinRefCount = minimumToolRefCount();
168  }; // end of outer loop
169 
170  //
171  // Second pass: Delete all finalized tools
172  //
173  // Delete in the order of increasing number of refCounts.
174  // Loop over tools in the same order as the order in which they were finalized.
175  // All tools in the list of finalized tools are no longer in the instancesTools list.
176  // If a tool destructor calls releaseTool() on another tool, this will have no
177  // effect on the 'other tool' if this 'other tool' is in the list of finalized tools.
178  // If this 'other tool' is still in the instancesTools list, it may trigger finalization
179  // (in releaseTool()), deletion and removal from the instancesTools list.
180  // Therefore, the check on non-finalised tools should happen *after* the deletion
181  // of the finalized tools.
182  ON_DEBUG debug() << "Deleting " << finalizedTools.size() << " finalized tools" << endmsg;
183  auto maxLoop = totalRefCount( finalizedTools ) + 1;
184  while ( --maxLoop > 0 && !finalizedTools.empty() ) {
185  IAlgTool* pTool = finalizedTools.front();
186  finalizedTools.pop_front();
187  auto count = pTool->refCount();
188  if ( count == 1 ) {
189  ON_DEBUG debug() << " Performing deletion of " << pTool->name() << endmsg;
190  } else {
191  ON_VERBOSE verbose() << " Delaying deletion of " << pTool->name() << " (refCount " << count << ")" << endmsg;
192  // Move to the end when refCount still not zero
193  finalizedTools.push_back( pTool );
194  }
195  // do a forced release
196  pTool->release();
197  }
198 
199  // Error if by now not all tools are properly finalised
200  if ( !m_instancesTools.empty() ) {
201  error() << "Unable to finalize and delete the following tools : ";
202  for ( const auto& iTool : m_instancesTools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
203  error() << endmsg;
204  }
205 
206  // by now, all tools should be deleted and removed.
207  if ( !finalizedTools.empty() ) {
208  error() << "Failed to delete the following " << finalizedTools.size()
209  << " finalized tools. Bug in ToolSvc::finalize()?: ";
210  for ( const auto& iTool : finalizedTools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
211  error() << endmsg;
212  }
213 
214  if ( m_pHistorySvc ) m_pHistorySvc->release();
215 
216  // Finalize this specific service
217  return ( Service::finalize().isSuccess() && !fail ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
218 }
219 
220 // ===================================================================================
224 // ===================================================================================
225 namespace {
226  static const std::string s_PUBLIC = ":PUBLIC";
227 }
228 
229 //------------------------------------------------------------------------------
230 StatusCode ToolSvc::retrieve( std::string_view tooltype, const InterfaceID& iid, IAlgTool*& tool,
231  const IInterface* parent, bool createIf )
232 //------------------------------------------------------------------------------
233 {
234  // check for tools, which by name are required to be public:
235  if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
236  // parent for PUBLIC tool is 'this', i.e. ToolSvc
237  tooltype.remove_suffix( s_PUBLIC.size() );
238  return retrieve( tooltype, iid, tool, this, createIf );
239  }
240 
241  // protect against empty type
242  if ( tooltype.empty() ) {
243  error() << "retrieve(): No Tool Type/Name given" << endmsg;
244  return StatusCode::FAILURE;
245  }
246  auto pos = tooltype.find( '/' );
247  if ( std::string_view::npos == pos ) { return retrieve( tooltype, tooltype, iid, tool, parent, createIf ); }
248  return retrieve( tooltype.substr( 0, pos ), tooltype.substr( pos + 1 ), iid, tool, parent, createIf );
249 }
250 
251 // ===================================================================================
252 
253 //------------------------------------------------------------------------------
254 StatusCode ToolSvc::retrieve( std::string_view tooltype, std::string_view toolname, const InterfaceID& iid,
255  IAlgTool*& tool, const IInterface* parent, bool createIf )
256 //------------------------------------------------------------------------------
257 {
258  // check the applicability of another method:
259  // ignore the provided name if it is empty or the type contains a name
260  if ( toolname.empty() || ( std::string_view::npos != tooltype.find( '/' ) ) ) {
261  return retrieve( tooltype, iid, tool, parent, createIf );
262  }
263 
264  // check for tools, which by name are required to be public:
265  if ( ba::ends_with( toolname, s_PUBLIC ) ) {
266  // parent for PUBLIC tool is this, i.e. ToolSvc
267  toolname.remove_suffix( s_PUBLIC.size() );
268  return retrieve( tooltype, toolname, iid, tool, this, createIf );
269  }
270 
271  auto lock = std::scoped_lock{ m_mut };
272 
273  IAlgTool* itool = nullptr;
275 
276  tool = nullptr;
277 
278  // If parent is not specified it means it is the ToolSvc itself
279  if ( !parent ) parent = this;
280  const std::string fullname = nameTool( toolname, parent );
281 
282  // Find tool in list of those already existing, and tell its
283  // interface that it has been used one more time
284  auto range = m_instancesToolsMap.equal_range( fullname );
285  auto it = std::find_if( range.first, range.second, [&]( auto const& p ) { return p.second->parent() == parent; } );
286  if ( it != range.second ) {
287  ON_DEBUG debug() << "Retrieved tool " << toolname << " with parent " << parent << endmsg;
288  itool = it->second;
289  }
290 
291  if ( !itool ) {
292  // Instances of this tool do not exist, create an instance if desired
293  // otherwise return failure
294  if ( !createIf ) {
295  warning() << "Tool " << toolname << " not found and creation not requested" << endmsg;
296  return sc;
297  }
298  sc = create( std::string{ tooltype }, std::string{ toolname }, parent, itool );
299  if ( sc.isFailure() ) { return sc; }
300  }
301 
302  // Get the right interface of it
303  sc = itool->queryInterface( iid, pp_cast<void>( &tool ) );
304  if ( sc.isFailure() ) {
305  error() << "Tool " << toolname << " either does not implement the correct interface, or its version is incompatible"
306  << endmsg;
307  return sc;
308  }
309 
314  [&]( IToolSvc::Observer* obs ) { obs->onRetrieve( itool ); } );
315  return sc;
316 }
317 //------------------------------------------------------------------------------
319 //------------------------------------------------------------------------------
320 {
321 
322  auto lock = std::scoped_lock{ m_mut };
324  for ( const auto& tool : m_instancesTools ) {
325  if ( tool->type() == toolType ) tools.push_back( tool->name() );
326  }
327  return tools;
328 }
329 //------------------------------------------------------------------------------
331 //------------------------------------------------------------------------------
332 {
333  auto lock = std::scoped_lock{ m_mut };
336  []( const IAlgTool* t ) { return t->name(); } );
337  return tools;
338 }
339 //------------------------------------------------------------------------------
341 //------------------------------------------------------------------------------
342 {
343  auto lock = std::scoped_lock{ m_mut };
345 }
346 //------------------------------------------------------------------------------
348 //------------------------------------------------------------------------------
349 {
350  auto lock = std::scoped_lock{ m_mut };
352  // test if tool is in known list (protect trying to access a previously deleted tool)
354  unsigned long count = tool->refCount();
355  if ( count == 1 ) {
356  // finalize the tool
357 
359  // We are being called during ToolSvc::finalize()
360  // message format matches the one in ToolSvc::finalize()
361  debug() << " Performing finalization of " << tool->name() << " (refCount " << count << ")" << endmsg;
362  // message format matches the one in ToolSvc::finalize()
363  debug() << " Performing deletion of " << tool->name() << endmsg;
364  } else {
365  debug() << "Performing finalization and deletion of " << tool->name() << endmsg;
366  }
367  sc = finalizeTool( tool );
368  // remove from known tools...
369  remove( m_instancesToolsMap, tool );
370  remove( m_instancesTools, tool );
371  }
372  tool->release();
373  }
374  return sc;
375 }
376 
377 //------------------------------------------------------------------------------
378 StatusCode ToolSvc::create( const std::string& tooltype, const IInterface* parent, IAlgTool*& tool )
379 //------------------------------------------------------------------------------
380 {
381  const std::string& toolname = tooltype;
382  return create( tooltype, toolname, parent, tool );
383 }
384 
385 namespace {
388  template <typename T, typename TM>
389  class ToolCreateGuard {
391  T& m_tools;
392  TM& m_toolsMap;
395 
396  public:
397  explicit ToolCreateGuard( T& tools, TM& toolsMap ) : m_tools( tools ), m_toolsMap( toolsMap ) {}
398  // we don't get a move constructor by default because we
399  // have a non-trivial destructor... However, the default
400  // one is just fine...
401  ToolCreateGuard( ToolCreateGuard&& ) noexcept = default;
403  void create( const std::string& tooltype, const std::string& fullname, const IInterface* parent ) {
404  // remove previous content
405  if ( m_tool ) {
406  remove( m_toolsMap, m_tool.get() );
407  remove( m_tools, m_tool.get() );
408  };
409  m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
410  // set new content
411  if ( m_tool ) {
412  m_tools.push_back( m_tool.get() );
413  m_toolsMap.emplace( m_tool->name(), m_tool.get() );
414  }
415  }
417  IAlgTool* get() { return m_tool.get(); }
418  IAlgTool* operator->() const {
419  assert( m_tool );
420  return m_tool.get();
421  }
423  IAlgTool* release() { return m_tool.release(); }
425  ~ToolCreateGuard() {
426  if ( m_tool ) remove( m_tools, m_tool.get() );
427  }
428  };
429 
430  template <typename C, typename CM>
431  ToolCreateGuard<C, CM> make_toolCreateGuard( C& c, CM& cm ) {
432  return ToolCreateGuard<C, CM>{ c, cm };
433  }
434 } // namespace
435 
436 //------------------------------------------------------------------------------
444 StatusCode ToolSvc::create( const std::string& tooltype, const std::string& toolname, const IInterface* parent,
445  IAlgTool*& tool )
446 //------------------------------------------------------------------------------
447 {
448 
449  auto lock = std::scoped_lock{ m_mut };
450  // protect against empty type
451  if ( tooltype.empty() ) {
452  error() << "create(): No Tool Type given" << endmsg;
453  return StatusCode::FAILURE;
454  }
455 
456  // If parent has not been specified, assume it is the ToolSvc
457  if ( !parent ) parent = this;
458 
459  tool = nullptr;
460  // Automatically deletes the tool if not explicitly kept (i.e. on success).
461  // The tool is removed from the list of known tools too.
462  auto toolguard = make_toolCreateGuard( m_instancesTools, m_instancesToolsMap );
463 
464  // Check if the tool already exist : this could happen with clones
465  std::string fullname = nameTool( toolname, parent );
466  if ( existsTool( fullname ) ) {
467  // Now check if the parent is the same. This allows for clones
468  for ( IAlgTool* iAlgTool : m_instancesTools ) {
469  if ( iAlgTool->name() == toolname && iAlgTool->parent() == parent ) {
470  // The tool exist with this name, type and parent: this is bad!
471  // This excludes the possibility of cloning public tools intrinsecally
472  error() << "Tool " << fullname << " already exists with the same parent" << endmsg;
473  if ( parent == this )
474  error() << "... In addition, the parent is the ToolSvc: public tools cannot be cloned!" << endmsg;
475 
476  return StatusCode::FAILURE;
477  }
478  }
479  ON_DEBUG debug() << "Creating clone of " << fullname << endmsg;
480  }
481  // instantiate the tool using the factory
482  try {
483  toolguard.create( tooltype, fullname, parent );
484  if ( !toolguard.get() ) {
485  error() << "Cannot create tool " << tooltype << " (No factory found)" << endmsg;
486  return StatusCode::FAILURE;
487  }
488  } catch ( const GaudiException& Exception ) {
489  // (1) perform the printout of message
490  fatal() << "Exception with tag=" << Exception.tag() << " is caught whilst instantiating tool '" << tooltype << "'"
491  << endmsg;
492  // (2) print the exception itself
493  // (NB! - GaudiException is a linked list of all "previous exceptions")
494  fatal() << Exception << endmsg;
495  return StatusCode::FAILURE;
496  } catch ( const std::exception& Exception ) {
497  // (1) perform the printout of message
498  fatal() << "Standard std::exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
499  // (2) print the exception itself
500  // (NB! - GaudiException is a linked list of all "previous exceptions")
501  fatal() << Exception.what() << endmsg;
502  return StatusCode::FAILURE;
503  } catch ( ... ) {
504  // (1) perform the printout
505  fatal() << "UNKNOWN Exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
506  return StatusCode::FAILURE;
507  }
508  ON_VERBOSE verbose() << "Created tool " << tooltype << "/" << fullname << endmsg;
509 
510  // Since only AlgTool has the setProperties() method it is necessary to cast
511  // to downcast IAlgTool to AlgTool in order to set the properties via the JobOptions
512  // service
513  AlgTool* mytool = dynamic_cast<AlgTool*>( toolguard.get() );
514  if ( mytool ) mytool->bindPropertiesTo( serviceLocator()->getOptsSvc() );
515 
516  // Initialize the Tool
518  try {
519  sc = toolguard->sysInitialize();
520  }
521  // Catch any exceptions
522  catch ( const GaudiException& Exception ) {
523  error() << "GaudiException with tag=" << Exception.tag() << " caught whilst initializing tool '" << fullname << "'"
524  << endmsg << Exception << endmsg;
525  return StatusCode::FAILURE;
526  } catch ( const std::exception& Exception ) {
527  error() << "Standard std::exception caught whilst initializing tool '" << fullname << "'" << endmsg
528  << Exception.what() << endmsg;
529  return StatusCode::FAILURE;
530  } catch ( ... ) {
531  error() << "UNKNOWN Exception caught whilst initializing tool '" << fullname << "'" << endmsg;
532  return StatusCode::FAILURE;
533  }
534 
535  // Status of tool initialization
536  if ( sc.isFailure() ) {
537  error() << "Error initializing tool '" << fullname << "'" << endmsg;
538  return sc;
539  }
540 
542  // Check to ensure that non-default named tools are configured.
543  if ( toolname != tooltype ) {
544  bool propsSet = false;
545  Gaudi::Interfaces::IOptionsSvc& joSvc = this->serviceLocator()->getOptsSvc();
546  // Check that at least one of the properties has been set:
547  for ( const auto prop : mytool->getProperties() ) {
548  bool isSet = joSvc.isSet( mytool->name() + "." + prop->name() );
549  if ( isSet ) propsSet = true;
550  }
551  if ( !propsSet ) {
552  warning() << tooltype << "/" << fullname
553  << " : Explicitly named tools should be configured! (assigned name=" << toolname << ", default is "
554  << tooltype << ")" << endmsg;
555  }
556  }
557  }
558 
559  // Start the tool if we are running.
561  sc = toolguard->sysStart();
562 
563  if ( sc.isFailure() ) {
564  error() << "Error starting tool '" << fullname << "'" << endmsg;
565  return sc;
566  }
567  }
568 
569  // The tool has been successfully created and initialized,
570  // so we inform the guard that it can release it
571  tool = toolguard.release();
572 
576  std::for_each( m_observers.begin(), m_observers.end(), [&]( IToolSvc::Observer* obs ) { obs->onCreate( tool ); } );
577  // TODO: replace by generic callback
578  // Register the tool with the HistorySvc
579  if ( m_pHistorySvc || service( "HistorySvc", m_pHistorySvc, false ).isSuccess() ) {
581  }
582  return StatusCode::SUCCESS;
583 }
584 
585 //------------------------------------------------------------------------------
586 std::string ToolSvc::nameTool( std::string_view toolname, const IInterface* parent )
587 //------------------------------------------------------------------------------
588 {
589 
590  if ( !parent ) { return std::string{ this->name() }.append( "." ).append( toolname ); } // RETURN
591 
592  // check that parent has a name!
593  auto named_parent = SmartIF<INamedInterface>( const_cast<IInterface*>( parent ) );
594  if ( named_parent ) {
595  auto fullname = std::string{ named_parent->name() }.append( "." ).append( toolname );
596  return fullname; // RETURN
597  }
598 
599  error() << "Private Tools only allowed for components implementing INamedInterface" << endmsg;
600  //
601  return std::string{ "." }.append( toolname );
602 }
603 
604 //------------------------------------------------------------------------------
605 bool ToolSvc::existsTool( std::string_view fullname ) const
606 //------------------------------------------------------------------------------
607 {
608  auto lock = std::scoped_lock{ m_mut };
609  return m_instancesToolsMap.find( fullname ) != std::end( m_instancesToolsMap );
610 }
611 
612 //------------------------------------------------------------------------------
614 //------------------------------------------------------------------------------
615 {
616 
617  // Cache tool name in case of errors
618  const auto& toolName = itool->name();
619  StatusCode sc;
620 
621  // Finalise the tool inside a try block
622  try {
623  sc = itool->sysFinalize();
624  }
625  // Catch any exceptions
626  catch ( const GaudiException& Exception ) {
627  error() << "GaudiException with tag=" << Exception.tag() << " caught whilst finalizing tool '" << toolName << "'"
628  << endmsg << Exception << endmsg;
629  sc = StatusCode::FAILURE;
630  } catch ( const std::exception& Exception ) {
631  error() << "Standard std::exception caught whilst finalizing tool '" << toolName << "'" << endmsg
632  << Exception.what() << endmsg;
633  sc = StatusCode::FAILURE;
634  } catch ( ... ) {
635  error() << "UNKNOWN Exception caught whilst finalizing tool '" << toolName << "'" << endmsg;
636  sc = StatusCode::FAILURE;
637  }
638 
639  return sc;
640 }
641 
642 //------------------------------------------------------------------------------
643 unsigned long ToolSvc::totalToolRefCount() const
644 //------------------------------------------------------------------------------
645 {
646  return totalRefCount( m_instancesTools );
647 }
648 //------------------------------------------------------------------------------
649 unsigned long ToolSvc::minimumToolRefCount() const
650 //------------------------------------------------------------------------------
651 {
652  auto i =
654  []( const IAlgTool* lhs, const IAlgTool* rhs ) { return lhs->refCount() < rhs->refCount(); } );
655  return i != std::end( m_instancesTools ) ? ( *i )->refCount() : 0;
656 }
657 
658 //------------------------------------------------------------------------------
660  //------------------------------------------------------------------------------
661  if ( !obs ) throw GaudiException( "Received NULL pointer", this->name() + "::registerObserver", StatusCode::FAILURE );
662 
663  auto lock = std::scoped_lock{ m_mut };
664  obs->setUnregister( [this, obs]() {
665  auto lock = std::scoped_lock{ m_mut };
666  auto i = std::find( m_observers.begin(), m_observers.end(), obs );
667  if ( i != m_observers.end() ) m_observers.erase( i );
668  } );
669  m_observers.push_back( obs );
670 }
671 
672 //------------------------------------------------------------------------------
674 //------------------------------------------------------------------------------
675 {
676 
677  ON_DEBUG debug() << "START transition for AlgTools" << endmsg;
678 
679  if ( m_showToolDataDeps.value() ) {
680  info() << "Listing Data Dependencies of all Tools";
681  for ( auto& iTool : m_instancesTools ) {
682  IDataHandleHolder* idh = dynamic_cast<IDataHandleHolder*>( iTool );
683  if ( idh ) {
684  std::ostringstream ost;
685  for ( auto& dh : idh->inputHandles() ) { ost << "\n INPUT " << dh->fullKey(); }
686  for ( auto& id : idh->extraInputDeps() ) { ost << "\n EXTRA INPUT " << id; }
687  for ( auto& dh : idh->outputHandles() ) { ost << "\n OUTPUT " << dh->fullKey(); }
688  for ( auto& id : idh->extraOutputDeps() ) { ost << "\n EXTRA OUTPUT " << id; }
689  if ( ost.str().length() > 0 ) { info() << "\n" << iTool->name() << ost.str(); }
690  } else {
691  error() << "can't cast " << iTool->name() << " to IDataHandleHolder!" << endmsg;
692  }
693  }
694  info() << endmsg;
695  }
696 
697  bool fail( false );
698  for ( auto& iTool : m_instancesTools ) {
699  ON_VERBOSE verbose() << iTool->name() << "::start()" << endmsg;
700 
701  if ( !iTool->sysStart().isSuccess() ) {
702  fail = true;
703  error() << iTool->name() << " failed to start()" << endmsg;
704  }
705  }
706 
707  if ( fail ) {
708  error() << "One or more AlgTools failed to start()" << endmsg;
709  return StatusCode::FAILURE;
710  }
711  return StatusCode::SUCCESS;
712 }
713 
714 //------------------------------------------------------------------------------
716 //------------------------------------------------------------------------------
717 {
718 
719  ON_DEBUG debug() << "STOP transition for AlgTools" << endmsg;
720 
721  bool fail( false );
722  for ( auto& iTool : m_instancesTools ) {
723  ON_VERBOSE verbose() << iTool->name() << "::stop()" << endmsg;
724 
725  if ( !iTool->sysStop().isSuccess() ) {
726  fail = true;
727  error() << iTool->name() << " failed to stop()" << endmsg;
728  }
729  }
730 
731  if ( fail ) {
732  error() << "One or more AlgTools failed to stop()" << endmsg;
733  return StatusCode::FAILURE;
734  }
735  return StatusCode::SUCCESS;
736 }
IDataHandleHolder
Definition: IDataHandleHolder.h:24
ToolSvc::m_observers
std::vector< IToolSvc::Observer * > m_observers
Definition: ToolSvc.h:112
ToolSvc::finalize
StatusCode finalize() override
Finalize the service.
Definition: ToolSvc.cpp:74
ToolSvc::m_instancesTools
std::vector< IAlgTool * > m_instancesTools
Common Tools.
Definition: ToolSvc.h:106
IHistorySvc::registerAlgTool
virtual StatusCode registerAlgTool(const IAlgTool &)=0
std::for_each
T for_each(T... args)
GaudiAlg.Algs.iAlgTool
iAlgTool
Definition: Algs.py:67
ToolSvc::finalizeTool
StatusCode finalizeTool(IAlgTool *itool) const
Finalize the given tool, with exception handling.
Definition: ToolSvc.cpp:613
std::string
STL class.
IAlgTool
Definition: IAlgTool.h:33
ToolSvc::nameTool
std::string nameTool(std::string_view nameByUser, const IInterface *parent)
Get Tool full name by combining nameByUser and "parent" part.
Definition: ToolSvc.cpp:586
std::exception
STL class.
Gaudi.Configuration.log
log
Definition: Configuration.py:29
IToolSvc::Observer::setUnregister
void setUnregister(std::function< void()> unregister)
Definition: IToolSvc.h:235
IDataHandleHolder::extraInputDeps
virtual const DataObjIDColl & extraInputDeps() const =0
Service::m_state
Gaudi::StateMachine::State m_state
Service state
Definition: Service.h:200
ToolSvc::getInstances
std::vector< std::string > getInstances() const override
Get names of all tool instances.
Definition: ToolSvc.cpp:330
GaudiException.h
ToolSvc::existsTool
bool existsTool(std::string_view fullname) const
Check if the tool instance exists.
Definition: ToolSvc.cpp:605
ToolSvc::m_instancesToolsMap
std::unordered_multimap< std::string_view, IAlgTool * > m_instancesToolsMap
Definition: ToolSvc.h:107
std::vector< std::string >
std::find_if
T find_if(T... args)
std::vector::size
T size(T... args)
GaudiException
Definition: GaudiException.h:31
GaudiPartProp.decorators.get
get
decorate the vector of properties
Definition: decorators.py:282
std::unique_ptr::get
T get(T... args)
INamedInterface::name
virtual const std::string & name() const =0
Retrieve the name of the instance.
std::unique_ptr::release
T release(T... args)
conf.release
string release
Definition: conf.py:27
IInterface::queryInterface
virtual StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.
gaudirun.c
c
Definition: gaudirun.py:525
std::vector::back
T back(T... args)
ToolSvc::getTools
std::vector< IAlgTool * > getTools() const override
Get pointers to all tool instances.
Definition: ToolSvc.cpp:340
ToolSvc
Definition: ToolSvc.h:35
ON_VERBOSE
#define ON_VERBOSE
Definition: ToolSvc.cpp:32
GaudiPartProp.tests.id
id
Definition: tests.py:111
Service::finalize
StatusCode finalize() override
Definition: Service.cpp:222
AlgTool::name
const std::string & name() const override
Retrieve full identifying name of the concrete tool object.
Definition: AlgTool.cpp:67
std::unordered_multimap< std::string_view, IAlgTool * >
PropertyHolder::bindPropertiesTo
void bindPropertiesTo(Gaudi::Interfaces::IOptionsSvc &optsSvc)
Definition: PropertyHolder.h:252
std::vector::push_back
T push_back(T... args)
ToolSvc::stop
StatusCode stop() override
Definition: ToolSvc.cpp:715
Service::tools
const std::vector< IAlgTool * > & tools() const
Definition: Service.cpp:409
PropertyHolder::getProperties
const std::vector< Gaudi::Details::PropertyBase * > & getProperties() const override
get all properties
Definition: PropertyHolder.h:222
ToolSvc::releaseTool
StatusCode releaseTool(IAlgTool *tool) override
Release tool.
Definition: ToolSvc.cpp:347
bug_34121.t
t
Definition: bug_34121.py:30
bug_34121.tool
tool
Definition: bug_34121.py:17
gaudirun.default
default
Definition: gaudirun.py:188
Service::name
const std::string & name() const override
Retrieve name of the service
Definition: Service.cpp:332
StatusCode
Definition: StatusCode.h:65
ToolSvc::m_pHistorySvc
IHistorySvc * m_pHistorySvc
Pointer to HistorySvc.
Definition: ToolSvc.h:110
IDataHandleHolder::extraOutputDeps
virtual const DataObjIDColl & extraOutputDeps() const =0
std::min_element
T min_element(T... args)
Gaudi::StateMachine::OFFLINE
@ OFFLINE
Definition: StateMachine.h:23
ToolSvc::m_checkNamedToolsConfigured
Gaudi::Property< bool > m_checkNamedToolsConfigured
Definition: ToolSvc.h:99
Gaudi::Property::value
const ValueType & value() const
Definition: Property.h:239
std::vector::erase
T erase(T... args)
std::accumulate
T accumulate(T... args)
SmartIF< INamedInterface >
genconfuser.verbose
verbose
Definition: genconfuser.py:28
ToolSvc::registerObserver
void registerObserver(IToolSvc::Observer *obs) override
Definition: ToolSvc.cpp:659
IHistorySvc.h
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
std::remove
T remove(T... args)
std::vector::pop_back
T pop_back(T... args)
std::transform
T transform(T... args)
IDataHandleHolder::inputHandles
virtual std::vector< Gaudi::DataHandle * > inputHandles() const =0
Gaudi::StateMachine::RUNNING
@ RUNNING
Definition: StateMachine.h:26
IToolSvc::Observer
allow call-backs when a tool is a created or retrieved
Definition: IToolSvc.h:230
std::string::append
T append(T... args)
std::vector::rend
T rend(T... args)
StatusCode::ignore
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
Definition: StatusCode.h:139
Service.h
ToolSvc::create
StatusCode create(const std::string &type, const IInterface *parent, IAlgTool *&tool)
Create Tool standard way with automatically assigned name.
Definition: ToolSvc.cpp:378
std::ostringstream
STL class.
StatusCode::isFailure
bool isFailure() const
Definition: StatusCode.h:129
std::unordered_multimap::equal_range
T equal_range(T... args)
ToolSvc::retrieve
StatusCode retrieve(std::string_view type, const InterfaceID &iid, IAlgTool *&tool, const IInterface *parent, bool createIf) override
Retrieve tool, create it by default as common tool if it does not already exist.
Definition: ToolSvc.cpp:230
Gaudi::Units::cm
constexpr double cm
Definition: SystemOfUnits.h:104
IToolSvc::Observer::onRetrieve
virtual void onRetrieve(const IAlgTool *)
Definition: IToolSvc.h:238
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
gaudirun.toolname
toolname
Definition: gaudirun.py:454
AlgTool
Definition: AlgTool.h:62
std::begin
T begin(T... args)
std
STL namespace.
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
std::vector::insert
T insert(T... args)
IInterface
Definition: IInterface.h:237
IDataHandleHolder::outputHandles
virtual std::vector< Gaudi::DataHandle * > outputHandles() const =0
std::vector::empty
T empty(T... args)
Service::m_targetState
Gaudi::StateMachine::State m_targetState
Service state
Definition: Service.h:202
AlgTool.h
std::ostringstream::str
T str(T... args)
ToolSvc::minimumToolRefCount
unsigned long minimumToolRefCount() const
The minimum number of refCounts of all tools.
Definition: ToolSvc.cpp:649
ON_DEBUG
#define ON_DEBUG
Definition: ToolSvc.cpp:31
ToolSvc::start
StatusCode start() override
Definition: ToolSvc.cpp:673
std::end
T end(T... args)
InterfaceID
Definition: IInterface.h:39
IAlgorithm.h
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
ToolSvc.h
IInterface::refCount
virtual unsigned long refCount() const =0
Current reference count.
IInterface::release
virtual unsigned long release()=0
Release Interface instance.
ISvcLocator.h
std::unique_ptr
STL class.
Gaudi::Interfaces::IOptionsSvc
Interface for a component that manages application configuration options.
Definition: IOptionsSvc.h:46
ToolSvc::m_showToolDataDeps
Gaudi::Property< bool > m_showToolDataDeps
Definition: ToolSvc.h:103
ToolSvc::totalToolRefCount
unsigned long totalToolRefCount() const
The total number of refCounts on all tools in the instancesTools list.
Definition: ToolSvc.cpp:643
Service::service
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn't already exist.
Definition: Service.h:88
std::vector::rbegin
T rbegin(T... args)
MsgStream.h
Gaudi::Functional::details::zip::range
decltype(auto) range(Args &&... args)
Zips multiple containers together to form a single range.
Definition: details.h:98
Service::serviceLocator
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator
Definition: Service.cpp:335
Gaudi::Interfaces::IOptionsSvc::isSet
virtual bool isSet(const std::string &key) const =0
Test if an option key was explicitly set or not.
ToolSvc::m_mut
CallMutex m_mut
Definition: ToolSvc.h:115