The Gaudi Framework  master (b9786168)
Loading...
Searching...
No Matches
ToolSvc.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11#include <GaudiKernel/AlgTool.h>
18#include <GaudiKernel/Service.h>
19#include <algorithm>
20#include <boost/circular_buffer.hpp>
21#include <cassert>
22#include <functional>
23#include <map>
24#include <mutex>
25#include <numeric>
26#include <string>
27#include <vector>
28
29#define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
30#define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
31
45class ToolSvc : public extends<Service, IToolSvc> {
46
47public:
48 using extends::extends;
49
50 ~ToolSvc() override;
51
53 StatusCode finalize() override;
54
55 // Start transition for tools
56 StatusCode start() override;
57
58 // Stop transition for tools
59 StatusCode stop() override;
60
62 StatusCode retrieve( std::string_view type, const InterfaceID& iid, IAlgTool*& tool, const IInterface* parent,
63 bool createIf ) override;
64
66 StatusCode retrieve( std::string_view tooltype, std::string_view toolname, const InterfaceID& iid, IAlgTool*& tool,
67 const IInterface* parent, bool createIf ) override;
68
70 std::vector<std::string> getInstances( std::string_view toolType ) override;
71
73 std::vector<std::string> getInstances() const override;
74
76 std::vector<IAlgTool*> getTools() const override;
77
79 StatusCode releaseTool( IAlgTool* tool ) override;
80
82 StatusCode create( const std::string& type, const IInterface* parent, IAlgTool*& tool );
83
85 StatusCode create( const std::string& type, const std::string& name, const IInterface* parent, IAlgTool*& tool );
86
88 bool existsTool( std::string_view fullname ) const;
89
91 std::string nameTool( std::string_view nameByUser, const IInterface* parent );
92
93 void registerObserver( IToolSvc::Observer* obs ) override;
94
95private:
97 StatusCode finalizeTool( IAlgTool* itool ) const;
98
100 this, "CheckedNamedToolsConfigured", false,
101 "Check that tools which do not have the default name have some explicit configuration." };
102
103 Gaudi::Property<bool> m_showToolDataDeps{ this, "ShowDataDeps", false, "show the data dependencies of AlgTools" };
104
106 this,
107 "AllowedPublicTools",
108 {},
109 "if non-empty, block the creation of public tools that are not listed in the set" };
110
112 class ToolList {
113 std::vector<IAlgTool*> m_tools; // List of all instances of tools
114 struct Hash {
115 using is_transparent = void;
116 std::size_t operator()( IAlgTool const* s ) const noexcept { return std::hash<std::string_view>{}( s->name() ); }
117 std::size_t operator()( std::string_view s ) const noexcept { return std::hash<std::string_view>{}( s ); }
118 };
119 struct Equal {
120 using is_transparent = void;
121 bool operator()( IAlgTool const* lhs, IAlgTool const* rhs ) const { return lhs->name() == rhs->name(); }
122 bool operator()( IAlgTool const* lhs, std::string_view rhs ) const { return lhs->name() == rhs; }
123 bool operator()( std::string_view lhs, IAlgTool const* rhs ) const { return lhs == rhs->name(); }
124 };
125 std::unordered_multiset<IAlgTool*, Hash, Equal> m_map;
126
127 public:
128 void remove( IAlgTool* tool ) {
129 m_tools.erase( std::remove( std::begin( m_tools ), std::end( m_tools ), tool ), std::end( m_tools ) );
130 auto range = m_map.equal_range( tool->name() );
131 auto itm = std::find_if( range.first, range.second, [&]( auto const& p ) { return p == tool; } );
132 if ( itm != range.second ) m_map.erase( itm );
133 }
134 void push_back( IAlgTool* tool ) {
135 m_tools.push_back( tool );
136 m_map.emplace( tool );
137 }
138
139 bool contains( std::string_view name ) const { return m_map.find( name ) != m_map.end(); }
140 bool contains( IAlgTool const* tool ) const {
141 return m_tools.rend() != std::find( m_tools.rbegin(), m_tools.rend(), tool );
142 // return tool == find( tool->name(), tool->parent() ); //FIXME: is this faster?
143 }
144 auto size() const { return m_tools.size(); }
145 auto begin() const { return m_tools.begin(); }
146 auto end() const { return m_tools.end(); }
147 auto find( std::string_view name, const IInterface* parent ) const {
148 auto range = m_map.equal_range( name );
149 auto it = std::find_if( range.first, range.second, [&]( auto const& p ) { return p->parent() == parent; } );
150 return it != range.second ? *it : nullptr;
151 }
152 std::vector<IAlgTool*> grab() && {
153 m_map.clear();
154 auto tools = std::move( m_tools );
155 return tools;
156 }
157 };
158 mutable std::recursive_mutex m_mut; // protect m_instancesTools
160
163
164 std::vector<IToolSvc::Observer*> m_observers;
165};
166
167namespace {
169 template <typename C>
170 unsigned long totalRefCount( const C& toolList ) {
171 return std::accumulate( begin( toolList ), end( toolList ), 0ul,
172 [&]( unsigned long count, const IAlgTool* tool ) { return count + tool->refCount(); } );
173 }
174
176 template <typename C>
177 unsigned long minimumRefCount( const C& toolList ) {
178 return std::accumulate( begin( toolList ), end( toolList ), ~0ul,
179 []( unsigned long c, const IAlgTool* tool ) { return std::min( c, tool->refCount() ); } );
180 }
181
182} // namespace
183
185
187 // tell the remaining observers that we're gone, and forget about unregistering..
188 std::for_each( std::begin( m_observers ), std::end( m_observers ),
189 [&]( IToolSvc::Observer* obs ) { obs->setUnregister( {} ); } );
190}
191
193 // Finalize and delete all left-over tools. Normally all tools created with
194 // ToolSvc are left over, since ToolSvc holds a refCount (via AlgTool ctor).
195 // Several cases need to be covered:
196 // 1) Simple dependencies: no circular dependencies between tools,
197 // and tools not using other tools
198 // 2) Tools-using-tools (but no circular dependencies)
199 // a) release() is called in the tool::finalize() (e.g. via base class)
200 // b) release() is called in the tool destructor (e.g. via ToolHandle)
201 // 3) Circular dependencies between tools
202 // a) release() is called in the tool::finalize() (e.g. via base class)
203 // b) release() is called in the tool destructor (e.g. via ToolHandle)
204 // 4) In addition to each of the above cases, refCounting of a particular tool
205 // might not have been done correctly in the code. Typically release()
206 // is not called, so we are left with a too high refCount.
207 // What to do with those, and how to avoid a crash while handling them...
208
217 info() << "Removing all tools created by ToolSvc" << endmsg;
218 auto tools = std::move( m_instancesTools ).grab();
219
220 // Print out list of tools
221 ON_DEBUG {
222 auto& log = debug();
223 log << " Tool List : ";
224 for ( const auto& iTool : tools ) { log << iTool->name() << ":" << iTool->refCount() << " "; }
225 log << endmsg;
226 }
227
228 //
229 // first pass: Finalize all tools (but don't delete them)
230 //
243 boost::circular_buffer<IAlgTool*> finalizedTools( tools.size() ); // list of tools that have been finalized
244 bool fail( false );
245 size_t toolCount = tools.size();
246 unsigned long startRefCount = 0;
247 unsigned long endRefCount = totalRefCount( tools );
248 unsigned long startMinRefCount = 0;
249 unsigned long endMinRefCount = minimumRefCount( tools );
250 while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
251 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
252 debug() << toolCount << " tools left to finalize. Summed refCounts: " << endRefCount << endmsg;
253 debug() << "Will finalize tools with refCount <= " << endMinRefCount << endmsg;
254 }
255 startMinRefCount = endMinRefCount;
256 startRefCount = endRefCount;
257 unsigned long maxLoop = toolCount + 1;
258 while ( --maxLoop > 0 && !tools.empty() ) {
259 IAlgTool* pTool = tools.back();
260 // removing tool from list makes ToolSvc::releaseTool( IAlgTool* ) a noop
261 tools.pop_back();
262 unsigned long count = pTool->refCount();
263 // cache tool name
264 const std::string& toolName = pTool->name();
265 if ( count <= startMinRefCount ) {
266 ON_DEBUG debug() << " Performing finalization of " << toolName << " (refCount " << count << ")" << endmsg;
267 // finalize of one tool may trigger a release of another tool
268 // pTool->sysFinalize().ignore();
269 if ( !finalizeTool( pTool ).isSuccess() ) {
270 warning() << " FAILURE finalizing " << toolName << endmsg;
271 fail = true;
272 }
273 // postpone deletion
274 finalizedTools.push_back( pTool );
275 } else {
276 // Place back at the front of the list to try again later
277 // ToolSvc::releaseTool( IAlgTool* ) remains active for this tool
278 ON_DEBUG debug() << " Delaying finalization of " << toolName << " (refCount " << count << ")" << endmsg;
279 tools.insert( std::begin( tools ), pTool );
280 }
281 } // end of inner loop
282 toolCount = tools.size();
283 endRefCount = totalRefCount( tools );
284 endMinRefCount = minimumRefCount( tools );
285 }; // end of outer loop
286
287 //
288 // Second pass: Delete all finalized tools
289 //
290 // Delete in the order of increasing number of refCounts.
291 // Loop over tools in the same order as the order in which they were finalized.
292 // All tools in the list of finalized tools are no longer in the instancesTools list.
293 // If a tool destructor calls releaseTool() on another tool, this will have no
294 // effect on the 'other tool' if this 'other tool' is in the list of finalized tools.
295 // If this 'other tool' is still in the instancesTools list, it may trigger finalization
296 // (in releaseTool()), deletion and removal from the instancesTools list.
297 // Therefore, the check on non-finalised tools should happen *after* the deletion
298 // of the finalized tools.
299 ON_DEBUG debug() << "Deleting " << finalizedTools.size() << " finalized tools" << endmsg;
300 auto maxLoop = totalRefCount( finalizedTools ) + 1;
301 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
302 IAlgTool* pTool = finalizedTools.front();
303 finalizedTools.pop_front();
304 auto count = pTool->refCount();
305 if ( count == 1 ) {
306 ON_DEBUG debug() << " Performing deletion of " << pTool->name() << endmsg;
307 } else {
308 ON_VERBOSE verbose() << " Delaying deletion of " << pTool->name() << " (refCount " << count << ")" << endmsg;
309 // Move to the end when refCount still not zero
310 finalizedTools.push_back( pTool );
311 }
312 // do a forced release
313 pTool->release();
314 }
315
316 // Error if by now not all tools are properly finalised
317 if ( !tools.empty() ) {
318 error() << "Unable to finalize and delete the following tools : ";
319 for ( const auto& iTool : tools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
320 error() << endmsg;
321 }
322
323 // by now, all tools should be deleted and removed.
324 if ( !finalizedTools.empty() ) {
325 error() << "Failed to delete the following " << finalizedTools.size()
326 << " finalized tools. Bug in ToolSvc::finalize()?: ";
327 for ( const auto& iTool : finalizedTools ) { error() << iTool->name() << ": " << iTool->refCount() << " "; }
328 error() << endmsg;
329 }
330
331 // Finalize this specific service
332 return ( Service::finalize().isSuccess() && !fail ) ? StatusCode::SUCCESS : StatusCode::FAILURE;
333}
334
335namespace {
336 constexpr std::string_view s_PUBLIC = ":PUBLIC";
337}
338
339StatusCode ToolSvc::retrieve( std::string_view tooltype, const InterfaceID& iid, IAlgTool*& tool,
340 const IInterface* parent, bool createIf ) {
341 // check for tools, which by name are required to be public:
342 if ( tooltype.ends_with( s_PUBLIC ) ) {
343 // parent for PUBLIC tool is 'this', i.e. ToolSvc
344 tooltype.remove_suffix( s_PUBLIC.size() );
345 return retrieve( tooltype, iid, tool, this, createIf );
346 }
347
348 // protect against empty type
349 if ( tooltype.empty() ) {
350 error() << "retrieve(): No Tool Type/Name given" << endmsg;
351 return StatusCode::FAILURE;
352 }
353 auto pos = tooltype.find( '/' );
354 if ( std::string_view::npos == pos ) { return retrieve( tooltype, tooltype, iid, tool, parent, createIf ); }
355 return retrieve( tooltype.substr( 0, pos ), tooltype.substr( pos + 1 ), iid, tool, parent, createIf );
356}
357
358StatusCode ToolSvc::retrieve( std::string_view tooltype, std::string_view toolname, const InterfaceID& iid,
359 IAlgTool*& tool, const IInterface* parent, bool createIf ) {
360 // check the applicability of another method:
361 // ignore the provided name if it is empty or the type contains a name
362 if ( toolname.empty() || ( std::string_view::npos != tooltype.find( '/' ) ) ) {
363 return retrieve( tooltype, iid, tool, parent, createIf );
364 }
365
366 // check for tools, which by name are required to be public:
367 if ( toolname.ends_with( s_PUBLIC ) ) {
368 // parent for PUBLIC tool is this, i.e. ToolSvc
369 toolname.remove_suffix( s_PUBLIC.size() );
370 return retrieve( tooltype, toolname, iid, tool, this, createIf );
371 }
372
373 tool = nullptr;
374
375 // If parent is not specified it means it is the ToolSvc itself
376 if ( !parent ) parent = this;
377 const std::string fullname = nameTool( toolname, parent );
378
379 // Find tool in list of those already existing, and tell its
380 // interface that it has been used one more time
381 auto lock = std::scoped_lock{ m_mut };
382 IAlgTool* itool = m_instancesTools.find( fullname, parent );
383 if ( itool ) { ON_DEBUG debug() << "Retrieved tool " << toolname << " with parent " << parent << endmsg; }
384
385 if ( !itool ) {
386 // Instances of this tool do not exist, create an instance if desired
387 // otherwise return failure
388 if ( !createIf ) {
389 warning() << "Tool " << toolname << " not found and creation not requested" << endmsg;
390 return StatusCode::FAILURE;
391 }
392 auto sc = create( std::string{ tooltype }, std::string{ toolname }, parent, itool );
393 if ( sc.isFailure() ) { return sc; }
394 }
395
396 // Get the right interface of it
397 tool = reinterpret_cast<IAlgTool*>( itool->i_cast( iid ) );
398 if ( !tool ) {
399 error() << "Tool " << toolname << " either does not implement the correct interface, or its version is incompatible"
400 << endmsg;
401 return StatusCode::FAILURE;
402 }
403 tool->addRef();
404
408 std::for_each( std::begin( m_observers ), std::end( m_observers ),
409 [&]( IToolSvc::Observer* obs ) { obs->onRetrieve( itool ); } );
410 return StatusCode::SUCCESS;
411}
412
413std::vector<std::string> ToolSvc::getInstances( std::string_view toolType ) {
414
415 std::vector<std::string> tools;
416 auto lock = std::scoped_lock{ m_mut };
417 for ( const auto& tool : m_instancesTools ) {
418 if ( tool->type() == toolType ) tools.push_back( tool->name() );
419 }
420 return tools;
421}
422
423std::vector<std::string> ToolSvc::getInstances() const {
424 auto lock = std::scoped_lock{ m_mut };
425 std::vector<std::string> tools{ m_instancesTools.size() };
426 std::transform( std::begin( m_instancesTools ), std::end( m_instancesTools ), std::begin( tools ),
427 []( const IAlgTool* t ) { return t->name(); } );
428 return tools;
429}
430
431std::vector<IAlgTool*> ToolSvc::getTools() const {
432 auto lock = std::scoped_lock{ m_mut };
433 return { std::begin( m_instancesTools ), std::end( m_instancesTools ) };
434}
435
437 auto lock = std::scoped_lock{ m_mut };
439 // test if tool is in known list (protect trying to access a previously deleted tool)
440 if ( m_instancesTools.contains( tool ) ) {
441 unsigned long count = tool->refCount();
442 if ( count == 1 ) {
443 // finalize the tool
444
446 // We are being called during ToolSvc::finalize()
447 // message format matches the one in ToolSvc::finalize()
448 debug() << " Performing finalization of " << tool->name() << " (refCount " << count << ")" << endmsg;
449 // message format matches the one in ToolSvc::finalize()
450 debug() << " Performing deletion of " << tool->name() << endmsg;
451 } else {
452 debug() << "Performing finalization and deletion of " << tool->name() << endmsg;
453 }
454 sc = finalizeTool( tool );
455 // remove from known tools...
456 m_instancesTools.remove( tool );
457 }
458 tool->release();
459 }
460 return sc;
461}
462
463StatusCode ToolSvc::create( const std::string& tooltype, const IInterface* parent, IAlgTool*& tool ) {
464 const std::string& toolname = tooltype;
465 return create( tooltype, toolname, parent, tool );
466}
467
468namespace {
471 template <typename T>
472 class ToolCreateGuard {
474 T& m_tools;
476 std::unique_ptr<IAlgTool> m_tool;
477
478 public:
479 explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
480 // we don't get a move constructor by default because we
481 // have a non-trivial destructor... However, the default
482 // one is just fine...
483 ToolCreateGuard( ToolCreateGuard&& ) noexcept = default;
485 void create( const std::string& tooltype, const std::string& fullname, const IInterface* parent ) {
486 // remove previous content
487 if ( m_tool ) { m_tools.remove( m_tool.get() ); };
488 m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
489 // set new content
490 if ( m_tool ) { m_tools.push_back( m_tool.get() ); }
491 }
493 IAlgTool* get() { return m_tool.get(); }
494 IAlgTool* operator->() const {
495 assert( m_tool );
496 return m_tool.get();
497 }
499 IAlgTool* release() { return m_tool.release(); }
501 ~ToolCreateGuard() {
502 if ( m_tool ) m_tools.remove( m_tool.get() );
503 }
504 };
505
506 template <typename C>
507 ToolCreateGuard<C> make_toolCreateGuard( C& c ) {
508 return ToolCreateGuard<C>{ c };
509 }
510} // namespace
511
519StatusCode ToolSvc::create( const std::string& tooltype, const std::string& toolname, const IInterface* parent,
520 IAlgTool*& tool ) {
521
522 // protect against empty type
523 if ( tooltype.empty() ) {
524 error() << "create(): No Tool Type given" << endmsg;
525 return StatusCode::FAILURE;
526 }
527
528 // If parent has not been specified, assume it is the ToolSvc
529 if ( !parent ) parent = this;
530
531 tool = nullptr;
532 // Automatically deletes the tool if not explicitly kept (i.e. on success).
533 // The tool is removed from the list of known tools too.
534 auto lock = std::scoped_lock{ m_mut };
535 auto toolguard = make_toolCreateGuard( m_instancesTools );
536
537 // Check if the tool already exist : this could happen with clones
538 std::string fullname = nameTool( toolname, parent );
539 if ( existsTool( fullname ) ) {
540 // Now check if the parent is the same. This allows for clones
541 for ( IAlgTool* iAlgTool : m_instancesTools ) {
542 if ( iAlgTool->name() == toolname && iAlgTool->parent() == parent ) {
543 // The tool exist with this name, type and parent: this is bad!
544 // This excludes the possibility of cloning public tools intrinsecally
545 error() << "Tool " << fullname << " already exists with the same parent" << endmsg;
546 if ( parent == this )
547 error() << "... In addition, the parent is the ToolSvc: public tools cannot be cloned!" << endmsg;
548
549 return StatusCode::FAILURE;
550 }
551 }
552 ON_DEBUG debug() << "Creating clone of " << fullname << endmsg;
553 }
554 // if there is a non-empty list of blessed public tools, only allow those to be created
555 if ( parent == this && !m_blessed_public_tools.empty() && !m_blessed_public_tools.value().contains( fullname ) ) {
556 error() << "Tool " << fullname << " is not in the list of allowed public tools" << endmsg;
557 return StatusCode::FAILURE;
558 }
559
560 // instantiate the tool using the factory
561 try {
562 toolguard.create( tooltype, fullname, parent );
563 if ( !toolguard.get() ) {
564 error() << "Cannot create tool " << tooltype << " (No factory found)" << endmsg;
565 return StatusCode::FAILURE;
566 }
567 } catch ( const GaudiException& Exception ) {
568 // (1) perform the printout of message
569 fatal() << "Exception with tag=" << Exception.tag() << " is caught whilst instantiating tool '" << tooltype << "'"
570 << endmsg;
571 // (2) print the exception itself
572 // (NB! - GaudiException is a linked list of all "previous exceptions")
573 fatal() << Exception << endmsg;
574 return StatusCode::FAILURE;
575 } catch ( const std::exception& Exception ) {
576 // (1) perform the printout of message
577 fatal() << "Standard std::exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
578 // (2) print the exception itself
579 // (NB! - GaudiException is a linked list of all "previous exceptions")
580 fatal() << Exception.what() << endmsg;
581 return StatusCode::FAILURE;
582 } catch ( ... ) {
583 // (1) perform the printout
584 fatal() << "UNKNOWN Exception is caught whilst instantiating tool '" << tooltype << "'" << endmsg;
585 return StatusCode::FAILURE;
586 }
587 ON_VERBOSE verbose() << "Created tool " << tooltype << "/" << fullname << endmsg;
588
589 // Since only AlgTool has the setProperties() method it is necessary to cast
590 // to downcast IAlgTool to AlgTool in order to set the properties via the JobOptions
591 // service
592 AlgTool* mytool = dynamic_cast<AlgTool*>( toolguard.get() );
593 if ( mytool ) mytool->bindPropertiesTo( serviceLocator()->getOptsSvc() );
594
595 // Initialize the Tool
597 try {
598 sc = toolguard->sysInitialize();
599 }
600 // Catch any exceptions
601 catch ( const GaudiException& Exception ) {
602 error() << "GaudiException with tag=" << Exception.tag() << " caught whilst initializing tool '" << fullname << "'"
603 << endmsg << Exception << endmsg;
604 return StatusCode::FAILURE;
605 } catch ( const std::exception& Exception ) {
606 error() << "Standard std::exception caught whilst initializing tool '" << fullname << "'" << endmsg
607 << Exception.what() << endmsg;
608 return StatusCode::FAILURE;
609 } catch ( ... ) {
610 error() << "UNKNOWN Exception caught whilst initializing tool '" << fullname << "'" << endmsg;
611 return StatusCode::FAILURE;
612 }
613
614 // Status of tool initialization
615 if ( sc.isFailure() ) {
616 error() << "Error initializing tool '" << fullname << "'" << endmsg;
617 return sc;
618 }
619
621 // Check to ensure that non-default named tools are configured.
622 if ( toolname != tooltype ) {
623 bool propsSet = false;
625 // Check that at least one of the properties has been set:
626 for ( const auto prop : mytool->getProperties() ) {
627 bool isSet = joSvc.isSet( mytool->name() + "." + prop->name() );
628 if ( isSet ) propsSet = true;
629 }
630 if ( !propsSet ) {
631 warning() << tooltype << "/" << fullname
632 << " : Explicitly named tools should be configured! (assigned name=" << toolname << ", default is "
633 << tooltype << ")" << endmsg;
634 }
635 }
636 }
637
638 // Start the tool if we are running.
640 sc = toolguard->sysStart();
641
642 if ( sc.isFailure() ) {
643 error() << "Error starting tool '" << fullname << "'" << endmsg;
644 return sc;
645 }
646 }
647
648 // The tool has been successfully created and initialized,
649 // so we inform the guard that it can release it
650 tool = toolguard.release();
651
655 std::for_each( m_observers.begin(), m_observers.end(), [&]( IToolSvc::Observer* obs ) { obs->onCreate( tool ); } );
656 // TODO: replace by generic callback
657 // Register the tool with the HistorySvc
658 m_pHistorySvc = service( "HistorySvc", false );
659 if ( m_pHistorySvc ) { m_pHistorySvc->registerAlgTool( *tool ).ignore(); }
660 return StatusCode::SUCCESS;
661}
662
663std::string ToolSvc::nameTool( std::string_view toolname, const IInterface* parent ) {
664
665 if ( !parent ) { return std::string{ this->name() }.append( "." ).append( toolname ); }
666
667 // check that parent has a name!
668 auto named_parent = SmartIF<INamedInterface>( const_cast<IInterface*>( parent ) );
669 if ( named_parent ) {
670 auto fullname = std::string{ named_parent->name() }.append( "." ).append( toolname );
671 return fullname;
672 }
673
674 error() << "Private Tools only allowed for components implementing INamedInterface" << endmsg;
675 //
676 return std::string{ "." }.append( toolname );
677}
678
679bool ToolSvc::existsTool( std::string_view fullname ) const {
680 auto lock = std::scoped_lock{ m_mut };
681 return m_instancesTools.contains( fullname );
682}
683
685
686 // Cache tool name in case of errors
687 const auto& toolName = itool->name();
688 StatusCode sc;
689
690 // Finalise the tool inside a try block
691 try {
692 sc = itool->sysFinalize();
693 }
694 // Catch any exceptions
695 catch ( const GaudiException& Exception ) {
696 error() << "GaudiException with tag=" << Exception.tag() << " caught whilst finalizing tool '" << toolName << "'"
697 << endmsg << Exception << endmsg;
699 } catch ( const std::exception& Exception ) {
700 error() << "Standard std::exception caught whilst finalizing tool '" << toolName << "'" << endmsg
701 << Exception.what() << endmsg;
703 } catch ( ... ) {
704 error() << "UNKNOWN Exception caught whilst finalizing tool '" << toolName << "'" << endmsg;
706 }
707
708 return sc;
709}
710
712 if ( !obs ) throw GaudiException( "Received NULL pointer", this->name() + "::registerObserver", StatusCode::FAILURE );
713
714 auto lock = std::scoped_lock{ m_mut };
715 obs->setUnregister( [this, obs]() {
716 auto lock = std::scoped_lock{ m_mut };
717 auto i = std::find( m_observers.begin(), m_observers.end(), obs );
718 if ( i != m_observers.end() ) m_observers.erase( i );
719 } );
720 m_observers.push_back( obs );
721}
722
724
725 ON_DEBUG debug() << "START transition for AlgTools" << endmsg;
726
727 if ( m_showToolDataDeps.value() ) {
728 info() << "Listing Data Dependencies of all Tools";
729 for ( auto& iTool : m_instancesTools ) {
730 IDataHandleHolder* idh = dynamic_cast<IDataHandleHolder*>( iTool );
731 if ( idh ) {
732 std::ostringstream ost;
733 for ( auto& dh : idh->inputHandles() ) { ost << "\n INPUT " << dh->fullKey(); }
734 for ( auto& id : idh->extraInputDeps() ) { ost << "\n EXTRA INPUT " << id; }
735 for ( auto& dh : idh->outputHandles() ) { ost << "\n OUTPUT " << dh->fullKey(); }
736 for ( auto& id : idh->extraOutputDeps() ) { ost << "\n EXTRA OUTPUT " << id; }
737 if ( ost.str().length() > 0 ) { info() << "\n" << iTool->name() << ost.str(); }
738 } else {
739 error() << "can't cast " << iTool->name() << " to IDataHandleHolder!" << endmsg;
740 }
741 }
742 info() << endmsg;
743 }
744
745 bool fail( false );
746 for ( auto& iTool : m_instancesTools ) {
747 ON_VERBOSE verbose() << iTool->name() << "::start()" << endmsg;
748
749 if ( !iTool->sysStart().isSuccess() ) {
750 fail = true;
751 error() << iTool->name() << " failed to start()" << endmsg;
752 }
753 }
754
755 if ( fail ) {
756 error() << "One or more AlgTools failed to start()" << endmsg;
757 return StatusCode::FAILURE;
758 }
759 return StatusCode::SUCCESS;
760}
761
763
764 ON_DEBUG debug() << "STOP transition for AlgTools" << endmsg;
765
766 bool fail( false );
767 for ( auto& iTool : m_instancesTools ) {
768 ON_VERBOSE verbose() << iTool->name() << "::stop()" << endmsg;
769
770 if ( !iTool->sysStop().isSuccess() ) {
771 fail = true;
772 error() << iTool->name() << " failed to stop()" << endmsg;
773 }
774 }
775
776 if ( fail ) {
777 error() << "One or more AlgTools failed to stop()" << endmsg;
778 return StatusCode::FAILURE;
779 }
780 return StatusCode::SUCCESS;
781}
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
#define DECLARE_COMPONENT(type)
#define ON_VERBOSE
Definition ToolSvc.cpp:30
#define ON_DEBUG
Definition ToolSvc.cpp:29
Base class from which all the concrete tool classes should be derived.
Definition AlgTool.h:55
const std::string & name() const override
Retrieve full identifying name of the concrete tool object.
Definition AlgTool.cpp:57
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
Implementation of property with value of concrete type.
Definition PropertyFwd.h:27
Define general base for Gaudi exception.
The interface implemented by the AlgTool base class.
Definition IAlgTool.h:29
virtual StatusCode sysFinalize()=0
Finalization of the Tool.
virtual const DataObjIDColl & extraOutputDeps() const =0
virtual std::vector< Gaudi::DataHandle * > outputHandles() const =0
virtual std::vector< Gaudi::DataHandle * > inputHandles() const =0
virtual const DataObjIDColl & extraInputDeps() const =0
Definition of the basic interface.
Definition IInterface.h:225
virtual void const * i_cast(const InterfaceID &) const =0
virtual unsigned long refCount() const =0
Current reference count.
virtual unsigned long release() const =0
Release Interface instance.
virtual const std::string & name() const =0
Retrieve the name of the instance.
Gaudi::Interfaces::IOptionsSvc & getOptsSvc()
Direct access to Gaudi::Interfaces::IOptionsSvc implementation.
allow call-backs when a tool is a created or retrieved
Definition IToolSvc.h:235
void setUnregister(std::function< void()> unregister)
Definition IToolSvc.h:240
virtual void onRetrieve(const IAlgTool *)
Definition IToolSvc.h:243
Interface ID class.
Definition IInterface.h:38
void bindPropertiesTo(Gaudi::Interfaces::IOptionsSvc &optsSvc)
const std::vector< Gaudi::Details::PropertyBase * > & getProperties() const override
get all properties
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator.
Definition Service.cpp:336
StatusCode finalize() override
Definition Service.cpp:223
const std::string & name() const override
Retrieve name of the service.
Definition Service.cpp:333
Gaudi::StateMachine::State m_targetState
Service state.
Definition Service.h:157
Gaudi::StateMachine::State m_state
Service state.
Definition Service.h:155
SmartIF< IFace > service(const std::string &name, bool createIf=true) const
Definition Service.h:79
const std::vector< IAlgTool * > & tools() const
Definition Service.cpp:411
Small smart pointer class with automatic reference counting for IInterface.
Definition SmartIF.h:28
This class is used for returning status codes from appropriate routines.
Definition StatusCode.h:64
bool isFailure() const
Definition StatusCode.h:129
constexpr static const auto SUCCESS
Definition StatusCode.h:99
constexpr static const auto FAILURE
Definition StatusCode.h:100
Common Tools.
Definition ToolSvc.cpp:112
auto end() const
Definition ToolSvc.cpp:146
auto find(std::string_view name, const IInterface *parent) const
Definition ToolSvc.cpp:147
std::vector< IAlgTool * > m_tools
Definition ToolSvc.cpp:113
auto size() const
Definition ToolSvc.cpp:144
auto begin() const
Definition ToolSvc.cpp:145
bool contains(IAlgTool const *tool) const
Definition ToolSvc.cpp:140
void push_back(IAlgTool *tool)
Definition ToolSvc.cpp:134
std::vector< IAlgTool * > grab() &&
Definition ToolSvc.cpp:152
void remove(IAlgTool *tool)
Definition ToolSvc.cpp:128
bool contains(std::string_view name) const
Definition ToolSvc.cpp:139
std::unordered_multiset< IAlgTool *, Hash, Equal > m_map
Definition ToolSvc.cpp:125
This service manages tools.
Definition ToolSvc.cpp:45
std::vector< IToolSvc::Observer * > m_observers
Definition ToolSvc.cpp:164
bool existsTool(std::string_view fullname) const
Check if the tool instance exists.
Definition ToolSvc.cpp:679
StatusCode finalizeTool(IAlgTool *itool) const
Finalize the given tool, with exception handling.
Definition ToolSvc.cpp:684
StatusCode releaseTool(IAlgTool *tool) override
Release tool.
Definition ToolSvc.cpp:436
std::vector< IAlgTool * > getTools() const override
Get pointers to all tool instances.
Definition ToolSvc.cpp:431
StatusCode create(const std::string &type, const IInterface *parent, IAlgTool *&tool)
Create Tool standard way with automatically assigned name.
Definition ToolSvc.cpp:463
StatusCode start() override
Definition ToolSvc.cpp:723
StatusCode finalize() override
Finalize the service.
Definition ToolSvc.cpp:192
void registerObserver(IToolSvc::Observer *obs) override
Definition ToolSvc.cpp:711
Gaudi::Property< std::set< std::string > > m_blessed_public_tools
Definition ToolSvc.cpp:105
std::recursive_mutex m_mut
Definition ToolSvc.cpp:158
std::string nameTool(std::string_view nameByUser, const IInterface *parent)
Get Tool full name by combining nameByUser and "parent" part.
Definition ToolSvc.cpp:663
ToolList m_instancesTools
Definition ToolSvc.cpp:159
StatusCode retrieve(std::string_view type, const InterfaceID &iid, IAlgTool *&tool, const IInterface *parent, bool createIf) override
Retrieve tool, create it by default as common tool if it does not already exist.
Definition ToolSvc.cpp:339
Gaudi::Property< bool > m_showToolDataDeps
Definition ToolSvc.cpp:103
Gaudi::Property< bool > m_checkNamedToolsConfigured
Definition ToolSvc.cpp:99
SmartIF< IHistorySvc > m_pHistorySvc
Pointer to HistorySvc.
Definition ToolSvc.cpp:162
std::vector< std::string > getInstances() const override
Get names of all tool instances.
Definition ToolSvc.cpp:423
StatusCode stop() override
Definition ToolSvc.cpp:762
~ToolSvc() override
Definition ToolSvc.cpp:186
Base class used to extend a class implementing other interfaces.
Definition extends.h:19
AttribStringParser::Iterator begin(const AttribStringParser &parser)
get
decorate the vector of properties
Definition decorators.py:94
str release
Definition conf.py:27
Interface for a component that manages application configuration options.
Definition IOptionsSvc.h:46
virtual bool isSet(const std::string &key) const =0
Test if an option key was explicitly set or not.
bool operator()(IAlgTool const *lhs, IAlgTool const *rhs) const
Definition ToolSvc.cpp:121
bool operator()(std::string_view lhs, IAlgTool const *rhs) const
Definition ToolSvc.cpp:123
bool operator()(IAlgTool const *lhs, std::string_view rhs) const
Definition ToolSvc.cpp:122
std::size_t operator()(IAlgTool const *s) const noexcept
Definition ToolSvc.cpp:116
std::size_t operator()(std::string_view s) const noexcept
Definition ToolSvc.cpp:117