Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ToolSvc.cpp
Go to the documentation of this file.
1 // Include Files
2 #include "ToolSvc.h"
3 #include "GaudiKernel/AlgTool.h"
9 #include "GaudiKernel/Service.h"
10 #include "boost/algorithm/string/erase.hpp"
11 #include "boost/algorithm/string/predicate.hpp"
12 #include "boost/circular_buffer.hpp"
13 #include <algorithm>
14 #include <cassert>
15 #include <functional>
16 #include <map>
17 #include <numeric>
18 #include <string>
19 namespace ba = boost::algorithm;
20 
21 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
22 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
23 
24 namespace {
25  //------------------------------------------------------------------------------
26  template <typename C>
27  unsigned long totalRefCount( const C& toolList )
28  //------------------------------------------------------------------------------
29  {
30  return std::accumulate( std::begin( toolList ), std::end( toolList ), 0ul,
31  [&]( unsigned long count, const IAlgTool* tool ) { return count + tool->refCount(); } );
32  }
33 
35  template <typename C>
36  void remove( C& c, typename C::const_reference i ) {
37  c.erase( std::remove( std::begin( c ), std::end( c ), i ), std::end( c ) );
38  }
39 } // namespace
40 
41 // Instantiation of a static factory class used by clients to create
42 // instances of this service
44 
45 //------------------------------------------------------------------------------
47  // tell the remaining observers that we're gone, and forget about unregistering..
48  std::for_each( std::begin( m_observers ), std::end( m_observers ),
49  [&]( IToolSvc::Observer* obs ) { obs->setUnregister( {} ); } );
50 }
51 //------------------------------------------------------------------------------
53 //------------------------------------------------------------------------------
54 {
55 
56  // initialize the Service Base class
58  if ( UNLIKELY( status.isFailure() ) ) {
59  error() << "Unable to initialize the Service" << endmsg;
60  return status;
61  }
62 
63  // set my own (ToolSvc) properties via the jobOptionService
64  if ( UNLIKELY( setProperties().isFailure() ) ) {
65  error() << "Unable to set base properties" << endmsg;
66  return StatusCode::FAILURE;
67  }
68 
69  return status;
70 }
71 
72 //------------------------------------------------------------------------------
74 //------------------------------------------------------------------------------
75 {
76  // Finalize and delete all left-over tools. Normally all tools created with
77  // ToolSvc are left over, since ToolSvc holds a refCount (via AlgTool ctor).
78  // Several cases need to be covered:
79  // 1) Simple dependencies: no circular dependencies between tools,
80  // and tools not using other tools
81  // 2) Tools-using-tools (but no circular dependencies)
82  // a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
83  // b) release() is called in the tool destructor (e.g. via ToolHandle)
84  // 3) Circular dependencies between tools
85  // a) release() is called in the tool::finalize() (e.g. via GaudiAlgorithm)
86  // b) release() is called in the tool destructor (e.g. via ToolHandle)
87  // 4) In addition to each of the above cases, refCounting of a particular tool
88  // might not have been done correctly in the code. Typically release()
89  // is not called, so we are left with a too high refCount.
90  // What to do with those, and how to avoid a crash while handling them...
91 
100  info() << "Removing all tools created by ToolSvc" << endmsg;
101 
102  // Print out list of tools
103  ON_DEBUG {
104  auto& log = debug();
105  log << " Tool List : ";
106  for ( const auto& iTool : m_instancesTools ) { log << iTool->name() << ":" << iTool->refCount() << " "; }
107  log << endmsg;
108  }
109 
110  //
111  // first pass: Finalize all tools (but don't delete them)
112  //
125  boost::circular_buffer<IAlgTool*> finalizedTools( m_instancesTools.size() ); // list of tools that have been finalized
126  bool fail( false );
127  size_t toolCount = m_instancesTools.size();
128  unsigned long startRefCount = 0;
129  unsigned long endRefCount = totalToolRefCount();
130  unsigned long startMinRefCount = 0;
131  unsigned long endMinRefCount = minimumToolRefCount();
132  while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
133  ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
134  debug() << toolCount << " tools left to finalize. Summed refCounts: " << endRefCount << endmsg;
135  debug() << "Will finalize tools with refCount <= " << endMinRefCount << endmsg;
136  }
137  startMinRefCount = endMinRefCount;
138  startRefCount = endRefCount;
139  unsigned long maxLoop = toolCount + 1;
140  while ( --maxLoop > 0 && !m_instancesTools.empty() ) {
141  IAlgTool* pTool = m_instancesTools.back();
142  // removing tool from list makes ToolSvc::releaseTool( IAlgTool* ) a noop
143  m_instancesTools.pop_back();
144  unsigned long count = pTool->refCount();
145  // cache tool name
146  const std::string& toolName = pTool->name();
147  if ( count <= startMinRefCount ) {
148  ON_DEBUG debug() << " Performing finalization of " << toolName << " (refCount " << count << ")" << endmsg;
149  // finalize of one tool may trigger a release of another tool
150  // pTool->sysFinalize().ignore();
151  if ( !finalizeTool( pTool ).isSuccess() ) {
152  warning() << " FAILURE finalizing " << toolName << endmsg;
153  fail = true;
154  }
155  // postpone deletion
156  finalizedTools.push_back( pTool );
157  } else {
158  // Place back at the front of the list to try again later
159  // ToolSvc::releaseTool( IAlgTool* ) remains active for this tool
160  ON_DEBUG debug() << " Delaying finalization of " << toolName << " (refCount " << count << ")" << endmsg;
161  m_instancesTools.insert( std::begin( m_instancesTools ), pTool );
162  }
163  } // end of inner loop
164  toolCount = m_instancesTools.size();
165  endRefCount = totalToolRefCount();
166  endMinRefCount = minimumToolRefCount();
167  }; // end of outer loop
168 
169  //
170  // Second pass: Delete all finalized tools
171  //
172  // Delete in the order of increasing number of refCounts.
173  // Loop over tools in the same order as the order in which they were finalized.
174  // All tools in the list of finalized tools are no longer in the instancesTools list.
175  // If a tool destructor calls releaseTool() on another tool, this will have no
176  // effect on the 'other tool' if this 'other tool' is in the list of finalized tools.
177  // If this 'other tool' is still in the instancesTools list, it may trigger finalization
178  // (in releaseTool()), deletion and removal from the instancesTools list.
179  // Therefore, the check on non-finalised tools should happen *after* the deletion
180  // of the finalized tools.
181  ON_DEBUG debug() << "Deleting " << finalizedTools.size() << " finalized tools" << endmsg;
182  auto maxLoop = totalRefCount( finalizedTools ) + 1;
183  while ( --maxLoop > 0 && !finalizedTools.empty() ) {
184  IAlgTool* pTool = finalizedTools.front();
185  finalizedTools.pop_front();
186  auto count = pTool->refCount();
187  if ( count == 1 ) {
188  ON_DEBUG debug() << " Performing deletion of " << pTool->name() << endmsg;
189  } else {
190  ON_VERBOSE verbose() << " Delaying deletion of " << pTool->name() << " (refCount " << count << ")" << endmsg;
191  // Move to the end when refCount still not zero
192  finalizedTools.push_back( pTool );
193  }
194  // do a forced release
195  pTool->release();
196  }
197 
198  // Error if by now not all tools are properly finalised
199  if ( !m_instancesTools.empty() ) {
200  error() << "Unable to finalize and delete the following tools : ";
201  for ( const auto& iTool : m_instancesTools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
202  error() << endmsg;
203  }
204 
205  // by now, all tools should be deleted and removed.
206  if ( !finalizedTools.empty() ) {
207  error() << "Failed to delete the following " << finalizedTools.size()
208  << " finalized tools. Bug in ToolSvc::finalize()?: ";
209  for ( const auto& iTool : finalizedTools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
210  error() << endmsg;
211  }
212 
213  if ( m_pHistorySvc ) m_pHistorySvc->release();
214 
215  // Finalize this specific service
216  return ( Service::finalize().isSuccess() && !fail ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
217 }
218 
219 // ===================================================================================
223 // ===================================================================================
224 namespace {
225  static const std::string s_PUBLIC = ":PUBLIC";
226 }
227 
228 //------------------------------------------------------------------------------
229 StatusCode ToolSvc::retrieve( const std::string& tooltype, const InterfaceID& iid, IAlgTool*& tool,
230  const IInterface* parent, bool createIf )
231 //------------------------------------------------------------------------------
232 {
233  // check for tools, which by name are required to be public:
234  if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
235  // parent for PUBLIC tool is 'this', i.e. ToolSvc
236  return retrieve( ba::erase_tail_copy( tooltype, s_PUBLIC.size() ), iid, tool, this, createIf );
237  }
238 
239  // protect against empty type
240  if ( tooltype.empty() ) {
241  error() << "retrieve(): No Tool Type/Name given" << endmsg;
242  return StatusCode::FAILURE;
243  }
244  auto pos = tooltype.find( '/' );
245  if ( std::string::npos == pos ) { return retrieve( tooltype, tooltype, iid, tool, parent, createIf ); }
246  return retrieve( tooltype.substr( 0, pos ), tooltype.substr( pos + 1 ), iid, tool, parent, createIf );
247 }
248 
249 // ===================================================================================
250 
251 //------------------------------------------------------------------------------
253  IAlgTool*& tool, const IInterface* parent, bool createIf )
254 //------------------------------------------------------------------------------
255 {
256  // check the applicability of another method:
257  // ignore the provided name if it is empty or the type contains a name
258  if ( toolname.empty() || ( std::string::npos != tooltype.find( '/' ) ) ) {
259  return retrieve( tooltype, iid, tool, parent, createIf );
260  }
261 
262  // check for tools, which by name are required to be public:
263  if ( ba::ends_with( toolname, s_PUBLIC ) ) {
264  // parent for PUBLIC tool is this, i.e. ToolSvc
265  return retrieve( tooltype, ba::erase_tail_copy( toolname, s_PUBLIC.size() ), iid, tool, this, createIf );
266  }
267 
268  std::lock_guard<CallMutex> lock( m_mut );
269 
270  IAlgTool* itool = nullptr;
272 
273  tool = nullptr;
274 
275  // If parent is not specified it means it is the ToolSvc itself
276  if ( !parent ) parent = this;
277  const std::string fullname = nameTool( toolname, parent );
278 
279  // Find tool in list of those already existing, and tell its
280  // interface that it has been used one more time
281  auto it = std::find_if( std::begin( m_instancesTools ), std::end( m_instancesTools ),
282  [&]( const IAlgTool* i ) { return i->name() == fullname && i->parent() == parent; } );
283  if ( it != std::end( m_instancesTools ) ) {
284  ON_DEBUG debug() << "Retrieved tool " << toolname << " with parent " << parent << endmsg;
285  itool = *it;
286  }
287 
288  if ( !itool ) {
289  // Instances of this tool do not exist, create an instance if desired
290  // otherwise return failure
291  if ( UNLIKELY( !createIf ) ) {
292  warning() << "Tool " << toolname << " not found and creation not requested" << endmsg;
293  return sc;
294  }
295  sc = create( tooltype, toolname, parent, itool );
296  if ( sc.isFailure() ) { return sc; }
297  }
298 
299  // Get the right interface of it
300  sc = itool->queryInterface( iid, pp_cast<void>( &tool ) );
301  if ( UNLIKELY( sc.isFailure() ) ) {
302  error() << "Tool " << toolname << " either does not implement the correct interface, or its version is incompatible"
303  << endmsg;
304  return sc;
305  }
306 
310  std::for_each( std::begin( m_observers ), std::end( m_observers ),
311  [&]( IToolSvc::Observer* obs ) { obs->onRetrieve( itool ); } );
312  return sc;
313 }
314 //------------------------------------------------------------------------------
316 //------------------------------------------------------------------------------
317 {
318 
319  std::lock_guard<CallMutex> lock( m_mut );
321  for ( const auto& tool : m_instancesTools ) {
322  if ( tool->type() == toolType ) tools.push_back( tool->name() );
323  }
324  return tools;
325 }
326 //------------------------------------------------------------------------------
328 //------------------------------------------------------------------------------
329 {
330  std::lock_guard<CallMutex> lock( m_mut );
331  std::vector<std::string> tools{m_instancesTools.size()};
332  std::transform( std::begin( m_instancesTools ), std::end( m_instancesTools ), std::begin( tools ),
333  []( const IAlgTool* t ) { return t->name(); } );
334  return tools;
335 }
336 //------------------------------------------------------------------------------
338 //------------------------------------------------------------------------------
339 {
340  std::lock_guard<CallMutex> lock( m_mut );
341  return std::vector<IAlgTool*>{std::begin( m_instancesTools ), std::end( m_instancesTools )};
342 }
343 //------------------------------------------------------------------------------
345 //------------------------------------------------------------------------------
346 {
347  std::lock_guard<CallMutex> lock( m_mut );
349  // test if tool is in known list (protect trying to access a previously deleted tool)
350  if ( m_instancesTools.rend() != std::find( m_instancesTools.rbegin(), m_instancesTools.rend(), tool ) ) {
351  unsigned long count = tool->refCount();
352  if ( count == 1 ) {
353  // finalize the tool
354 
355  if ( Gaudi::StateMachine::OFFLINE == m_targetState ) {
356  // We are being called during ToolSvc::finalize()
357  // message format matches the one in ToolSvc::finalize()
358  debug() << " Performing finalization of " << tool->name() << " (refCount " << count << ")" << endmsg;
359  // message format matches the one in ToolSvc::finalize()
360  debug() << " Performing deletion of " << tool->name() << endmsg;
361  } else {
362  debug() << "Performing finalization and deletion of " << tool->name() << endmsg;
363  }
364  sc = finalizeTool( tool );
365  // remove from known tools...
366  remove( m_instancesTools, tool );
367  }
368  tool->release();
369  }
370  return sc;
371 }
372 
373 //------------------------------------------------------------------------------
374 StatusCode ToolSvc::create( const std::string& tooltype, const IInterface* parent, IAlgTool*& tool )
375 //------------------------------------------------------------------------------
376 {
377  const std::string& toolname = tooltype;
378  return create( tooltype, toolname, parent, tool );
379 }
380 
381 namespace {
384  template <typename T>
385  class ToolCreateGuard {
387  T& m_tools;
390 
391  public:
392  explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
393  // we don't get a move constructor by default because we
394  // have a non-trivial destructor... However, the default
395  // one is just fine...
396  ToolCreateGuard( ToolCreateGuard&& ) noexcept = default;
398  void create( const std::string& tooltype, const std::string& fullname, const IInterface* parent ) {
399  // remove previous content
400  if ( m_tool ) remove( m_tools, m_tool.get() );
401  m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
402  // set new content
403  if ( m_tool ) m_tools.push_back( m_tool.get() );
404  }
406  IAlgTool* get() { return m_tool.get(); }
407  IAlgTool* operator->() const {
408  assert( m_tool );
409  return m_tool.get();
410  }
412  IAlgTool* release() { return m_tool.release(); }
414  ~ToolCreateGuard() {
415  if ( m_tool ) remove( m_tools, m_tool.get() );
416  }
417  };
418 
419  template <typename C>
420  ToolCreateGuard<C> make_toolCreateGuard( C& c ) {
421  return ToolCreateGuard<C>{c};
422  }
423 } // namespace
424 
425 //------------------------------------------------------------------------------
433 StatusCode ToolSvc::create( const std::string& tooltype, const std::string& toolname, const IInterface* parent,
434  IAlgTool*& tool )
435 //------------------------------------------------------------------------------
436 {
437 
438  std::lock_guard<CallMutex> lock( m_mut );
439  // protect against empty type
440  if ( UNLIKELY( tooltype.empty() ) ) {
441  error() << "create(): No Tool Type given" << endmsg;
442  return StatusCode::FAILURE;
443  }
444 
445  // If parent has not been specified, assume it is the ToolSvc
446  if ( !parent ) parent = this;
447 
448  tool = nullptr;
449  // Automatically deletes the tool if not explicitly kept (i.e. on success).
450  // The tool is removed from the list of known tools too.
451  auto toolguard = make_toolCreateGuard( m_instancesTools );
452 
453  // Check if the tool already exist : this could happen with clones
454  std::string fullname = nameTool( toolname, parent );
455  if ( UNLIKELY( existsTool( fullname ) ) ) {
456  // Now check if the parent is the same. This allows for clones
457  for ( IAlgTool* iAlgTool : m_instancesTools ) {
458  if ( iAlgTool->name() == toolname && iAlgTool->parent() == parent ) {
459  // The tool exist with this name, type and parent: this is bad!
460  // This excludes the possibility of cloning public tools intrinsecally
461  error() << "Tool " << fullname << " already exists with the same parent" << endmsg;
462  if ( parent == this )
463  error() << "... In addition, the parent is the ToolSvc: public tools cannot be cloned!" << endmsg;
464 
465  return StatusCode::FAILURE;
466  }
467  }
468  ON_DEBUG debug() << "Creating clone of " << fullname << endmsg;
469  }
470  // instantiate the tool using the factory
471  try {
472  toolguard.create( tooltype, fullname, parent );
473  if ( UNLIKELY( !toolguard.get() ) ) {
474  error() << "Cannot create tool " << tooltype << " (No factory found)" << endmsg;
475  return StatusCode::FAILURE;
476  }
477  } catch ( const GaudiException& Exception ) {
478  // (1) perform the printout of message
479  fatal() << "Exception with tag=" << Exception.tag() << " is caught whilst instantiating tool '" << tooltype << "'"
480  << endmsg;
481  // (2) print the exception itself
482  // (NB! - GaudiException is a linked list of all "previous exceptions")
483  fatal() << Exception << endmsg;
484  return StatusCode::FAILURE;
485  } catch ( const std::exception& Exception ) {
486  // (1) perform the printout of message
487  fatal() << "Standard std::exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
488  // (2) print the exception itself
489  // (NB! - GaudiException is a linked list of all "previous exceptions")
490  fatal() << Exception.what() << endmsg;
491  return StatusCode::FAILURE;
492  } catch ( ... ) {
493  // (1) perform the printout
494  fatal() << "UNKNOWN Exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
495  return StatusCode::FAILURE;
496  }
497  ON_VERBOSE verbose() << "Created tool " << tooltype << "/" << fullname << endmsg;
498 
499  // Since only AlgTool has the setProperties() method it is necessary to cast
500  // to downcast IAlgTool to AlgTool in order to set the properties via the JobOptions
501  // service
502  AlgTool* mytool = dynamic_cast<AlgTool*>( toolguard.get() );
503  if ( mytool ) {
504  StatusCode sc = mytool->setProperties();
505  if ( UNLIKELY( sc.isFailure() ) ) {
506  error() << "Error setting properties for tool '" << fullname << "'" << endmsg;
507  return sc;
508  }
509  }
510 
511  // Initialize the Tool
512  StatusCode sc( StatusCode::FAILURE, true );
513  try {
514  sc = toolguard->sysInitialize();
515  }
516  // Catch any exceptions
517  catch ( const GaudiException& Exception ) {
518  error() << "GaudiException with tag=" << Exception.tag() << " caught whilst initializing tool '" << fullname << "'"
519  << endmsg << Exception << endmsg;
520  return StatusCode::FAILURE;
521  } catch ( const std::exception& Exception ) {
522  error() << "Standard std::exception caught whilst initializing tool '" << fullname << "'" << endmsg
523  << Exception.what() << endmsg;
524  return StatusCode::FAILURE;
525  } catch ( ... ) {
526  error() << "UNKNOWN Exception caught whilst initializing tool '" << fullname << "'" << endmsg;
527  return StatusCode::FAILURE;
528  }
529 
530  // Status of tool initialization
531  if ( UNLIKELY( sc.isFailure() ) ) {
532  error() << "Error initializing tool '" << fullname << "'" << endmsg;
533  return sc;
534  }
535 
536  // Start the tool if we are running.
537  if ( m_state == Gaudi::StateMachine::RUNNING ) {
538  sc = toolguard->sysStart();
539 
540  if ( UNLIKELY( sc.isFailure() ) ) {
541  error() << "Error starting tool '" << fullname << "'" << endmsg;
542  return sc;
543  }
544  }
545 
546  // The tool has been successfully created and initialized,
547  // so we inform the guard that it can release it
548  tool = toolguard.release();
549 
553  std::for_each( m_observers.begin(), m_observers.end(), [&]( IToolSvc::Observer* obs ) { obs->onCreate( tool ); } );
554  // TODO: replace by generic callback
555  // Register the tool with the HistorySvc
556  if ( m_pHistorySvc || service( "HistorySvc", m_pHistorySvc, false ).isSuccess() ) {
557  m_pHistorySvc->registerAlgTool( *tool ).ignore();
558  }
559  return StatusCode::SUCCESS;
560 }
561 
562 //------------------------------------------------------------------------------
564 //------------------------------------------------------------------------------
565 {
566 
567  if ( !parent ) { return this->name() + "." + toolname; } // RETURN
568 
569  // check that parent has a name!
570  auto named_parent = SmartIF<INamedInterface>( const_cast<IInterface*>( parent ) );
571  if ( named_parent ) {
572  auto fullname = named_parent->name() + "." + toolname;
573  return fullname; // RETURN
574  }
575 
576  error() << "Private Tools only allowed for components implementing INamedInterface" << endmsg;
577  //
578  return "." + toolname;
579 }
580 
581 //------------------------------------------------------------------------------
582 bool ToolSvc::existsTool( const std::string& fullname ) const
583 //------------------------------------------------------------------------------
584 {
585  std::lock_guard<CallMutex> lock( m_mut );
586  auto i = std::find_if( std::begin( m_instancesTools ), std::end( m_instancesTools ),
587  [&]( const IAlgTool* tool ) { return tool->name() == fullname; } );
588  return i != std::end( m_instancesTools );
589 }
590 
591 //------------------------------------------------------------------------------
593 //------------------------------------------------------------------------------
594 {
595 
596  // Cache tool name in case of errors
597  const std::string toolName = itool->name();
598  StatusCode sc;
599 
600  // Finalise the tool inside a try block
601  try {
602  sc = itool->sysFinalize();
603  }
604  // Catch any exceptions
605  catch ( const GaudiException& Exception ) {
606  error() << "GaudiException with tag=" << Exception.tag() << " caught whilst finalizing tool '" << toolName << "'"
607  << endmsg << Exception << endmsg;
608  sc = StatusCode::FAILURE;
609  } catch ( const std::exception& Exception ) {
610  error() << "Standard std::exception caught whilst finalizing tool '" << toolName << "'" << endmsg
611  << Exception.what() << endmsg;
612  sc = StatusCode::FAILURE;
613  } catch ( ... ) {
614  error() << "UNKNOWN Exception caught whilst finalizing tool '" << toolName << "'" << endmsg;
615  sc = StatusCode::FAILURE;
616  }
617 
618  return sc;
619 }
620 
621 //------------------------------------------------------------------------------
622 unsigned long ToolSvc::totalToolRefCount() const
623 //------------------------------------------------------------------------------
624 {
625  return totalRefCount( m_instancesTools );
626 }
627 //------------------------------------------------------------------------------
628 unsigned long ToolSvc::minimumToolRefCount() const
629 //------------------------------------------------------------------------------
630 {
631  auto i =
632  std::min_element( std::begin( m_instancesTools ), std::end( m_instancesTools ),
633  []( const IAlgTool* lhs, const IAlgTool* rhs ) { return lhs->refCount() < rhs->refCount(); } );
634  return i != std::end( m_instancesTools ) ? ( *i )->refCount() : 0;
635 }
636 
637 //------------------------------------------------------------------------------
639  //------------------------------------------------------------------------------
640  if ( !obs ) throw GaudiException( "Received NULL pointer", this->name() + "::registerObserver", StatusCode::FAILURE );
641 
642  std::lock_guard<CallMutex> lock( m_mut );
643  obs->setUnregister( [this, obs]() {
644  std::lock_guard<CallMutex> lock( m_mut );
645  auto i = std::find( m_observers.begin(), m_observers.end(), obs );
646  if ( i != m_observers.end() ) m_observers.erase( i );
647  } );
648  m_observers.push_back( obs );
649 }
650 
651 //------------------------------------------------------------------------------
653 //------------------------------------------------------------------------------
654 {
655 
656  ON_DEBUG debug() << "START transition for AlgTools" << endmsg;
657 
658  bool fail( false );
659  for ( auto& iTool : m_instancesTools ) {
660  ON_VERBOSE verbose() << iTool->name() << "::start()" << endmsg;
661 
662  if ( UNLIKELY( !iTool->sysStart().isSuccess() ) ) {
663  fail = true;
664  error() << iTool->name() << " failed to start()" << endmsg;
665  }
666  }
667 
668  if ( UNLIKELY( fail ) ) {
669  error() << "One or more AlgTools failed to start()" << endmsg;
670  return StatusCode::FAILURE;
671  }
672  return StatusCode::SUCCESS;
673 }
674 
675 //------------------------------------------------------------------------------
677 //------------------------------------------------------------------------------
678 {
679 
680  ON_DEBUG debug() << "STOP transition for AlgTools" << endmsg;
681 
682  bool fail( false );
683  for ( auto& iTool : m_instancesTools ) {
684  ON_VERBOSE verbose() << iTool->name() << "::stop()" << endmsg;
685 
686  if ( UNLIKELY( !iTool->sysStop().isSuccess() ) ) {
687  fail = true;
688  error() << iTool->name() << " failed to stop()" << endmsg;
689  }
690  }
691 
692  if ( UNLIKELY( fail ) ) {
693  error() << "One or more AlgTools failed to stop()" << endmsg;
694  return StatusCode::FAILURE;
695  }
696  return StatusCode::SUCCESS;
697 }
#define UNLIKELY(x)
Definition: Kernel.h:89
StatusCode initialize() override
Definition: Service.cpp:60
T empty(T...args)
Define general base for Gaudi exception.
StatusCode releaseTool(IAlgTool *tool) override
Release tool.
Definition: ToolSvc.cpp:344
StatusCode finalize() override
Definition: Service.cpp:164
std::string nameTool(const std::string &nameByUser, const IInterface *parent)
Get Tool full name by combining nameByUser and "parent" part.
Definition: ToolSvc.cpp:563
allow call-backs when a tool is a created or retrieved
Definition: IToolSvc.h:221
unsigned long minimumToolRefCount() const
The minimum number of refCounts of all tools.
Definition: ToolSvc.cpp:628
StatusCode create(const std::string &type, const IInterface *parent, IAlgTool *&tool)
Create Tool standard way with automatically assigned name.
Definition: ToolSvc.cpp:374
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
std::vector< std::string > getInstances() const override
Get names of all tool instances.
Definition: ToolSvc.cpp:327
void registerObserver(IToolSvc::Observer *obs) override
Definition: ToolSvc.cpp:638
T end(T...args)
T remove(T...args)
bool existsTool(const std::string &toolname) const
Check if the tool instance exists.
Definition: ToolSvc.cpp:582
bool isFailure() const
Definition: StatusCode.h:130
StatusCode initialize() override
Initialize the service.
Definition: ToolSvc.cpp:52
This service manages tools.
Definition: ToolSvc.h:24
T release(T...args)
StatusCode setProperties()
Method for setting declared properties to the values specified in the jobOptions via the job option s...
Definition: AlgTool.cpp:107
STL class.
#define DECLARE_COMPONENT(type)
StatusCode start() override
Definition: ToolSvc.cpp:652
virtual void onCreate(const IAlgTool *)
Definition: IToolSvc.h:228
T push_back(T...args)
Interface ID class.
Definition: IInterface.h:29
unsigned long totalToolRefCount() const
The total number of refCounts on all tools in the instancesTools list.
Definition: ToolSvc.cpp:622
StatusCode finalizeTool(IAlgTool *itool) const
Finalize the given tool, with exception handling.
Definition: ToolSvc.cpp:592
T what(T...args)
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
Definition of the basic interface.
Definition: IInterface.h:244
virtual const std::string & tag() const
name tag for the exception, or exception type
STL class.
T get(T...args)
T find(T...args)
T size(T...args)
void setUnregister(std::function< void()> unregister)
Definition: IToolSvc.h:226
virtual unsigned long release()=0
Release Interface instance.
STL class.
T begin(T...args)
virtual void onRetrieve(const IAlgTool *)
Definition: IToolSvc.h:229
Base class from which all the concrete tool classes should be derived.
Definition: AlgTool.h:47
The interface implemented by the AlgTool base class.
Definition: IAlgTool.h:23
#define ON_DEBUG
Definition: ToolSvc.cpp:21
StatusCode finalize() override
Finalize the service.
Definition: ToolSvc.cpp:73
constexpr static const auto FAILURE
Definition: StatusCode.h:86
T substr(T...args)
std::vector< IAlgTool * > getTools() const override
Get pointers to all tool instances.
Definition: ToolSvc.cpp:337
T transform(T...args)
virtual unsigned long refCount() const =0
Current reference count.
T accumulate(T...args)
T min_element(T...args)
T for_each(T...args)
virtual const IInterface * parent() const =0
The parent of the concrete AlgTool.
StatusCode stop() override
Definition: ToolSvc.cpp:676
#define ON_VERBOSE
Definition: ToolSvc.cpp:22
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
virtual const std::string & name() const =0
Retrieve the name of the instance.
virtual StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.
StatusCode retrieve(const std::string &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:229