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