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