The Gaudi Framework  master (e68eea06)
Loading...
Searching...
No Matches
ToolSvc Class Reference

This service manages tools. More...

Inheritance diagram for ToolSvc:
Collaboration diagram for ToolSvc:

Classes

class  ToolList
 Common Tools. More...
 

Public Member Functions

 ~ToolSvc () override
 
StatusCode finalize () override
 Finalize the service.
 
StatusCode start () override
 
StatusCode stop () override
 
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.
 
StatusCode retrieve (std::string_view tooltype, std::string_view toolname, 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.
 
std::vector< std::string > getInstances (std::string_view toolType) override
 Get names of all tool instances of a given type.
 
std::vector< std::string > getInstances () const override
 Get names of all tool instances.
 
std::vector< IAlgTool * > getTools () const override
 Get pointers to all tool instances.
 
StatusCode releaseTool (IAlgTool *tool) override
 Release tool.
 
StatusCode create (const std::string &type, const IInterface *parent, IAlgTool *&tool)
 Create Tool standard way with automatically assigned name.
 
StatusCode create (const std::string &type, const std::string &name, const IInterface *parent, IAlgTool *&tool)
 Create Tool standard way with specified name.
 
bool existsTool (std::string_view fullname) const
 Check if the tool instance exists.
 
std::string nameTool (std::string_view nameByUser, const IInterface *parent)
 Get Tool full name by combining nameByUser and "parent" part.
 
void registerObserver (IToolSvc::Observer *obs) override
 
- Public Member Functions inherited from extends< Service, IToolSvc >
void const * i_cast (const InterfaceID &tid) const override
 Implementation of IInterface::i_cast.
 
StatusCode queryInterface (const InterfaceID &ti, void **pp) override
 Implementation of IInterface::queryInterface.
 
std::vector< std::string > getInterfaceNames () const override
 Implementation of IInterface::getInterfaceNames.
 
- Public Member Functions inherited from Service
const std::string & name () const override
 Retrieve name of the service.
 
StatusCode configure () override
 
StatusCode initialize () override
 
StatusCode start () override
 
StatusCode stop () override
 
StatusCode finalize () override
 
StatusCode terminate () override
 
Gaudi::StateMachine::State FSMState () const override
 
Gaudi::StateMachine::State targetFSMState () const override
 
StatusCode reinitialize () override
 
StatusCode restart () override
 
StatusCode sysInitialize () override
 Initialize Service.
 
StatusCode sysStart () override
 Initialize Service.
 
StatusCode sysStop () override
 Initialize Service.
 
StatusCode sysFinalize () override
 Finalize Service.
 
StatusCode sysReinitialize () override
 Re-initialize the Service.
 
StatusCode sysRestart () override
 Re-initialize the Service.
 
 Service (std::string name, ISvcLocator *svcloc)
 Standard Constructor.
 
SmartIF< ISvcLocator > & serviceLocator () const override
 Retrieve pointer to service locator.
 
template<typename IFace = IService>
SmartIF< IFace > service (const std::string &name, bool createIf=true) const
 
template<class T>
Gaudi::Details::PropertyBasedeclareProperty (const std::string &name, ToolHandle< T > &hndl, const std::string &doc="none")
 
template<class T>
StatusCode declareTool (ToolHandle< T > &handle, bool createIf=true)
 
template<class T>
StatusCode declareTool (ToolHandle< T > &handle, const std::string &toolTypeAndName, bool createIf=true)
 Declare used tool.
 
template<class T>
Gaudi::Details::PropertyBasedeclareProperty (const std::string &name, ToolHandleArray< T > &hndlArr, const std::string &doc="none")
 
template<class T>
void addToolsArray (ToolHandleArray< T > &hndlArr)
 
const std::vector< IAlgTool * > & tools () const
 
SmartIF< IAuditorSvc > & auditorSvc () const
 The standard auditor service.May not be invoked before sysInitialize() has been invoked.
 
- Public Member Functions inherited from PropertyHolder< CommonMessaging< implements< IService, IProperty, IStateful > > >
StatusCode setProperty (const Gaudi::Details::PropertyBase &p)
 Set the property from a property.
 
StatusCode setProperty (const std::string &name, const char *v)
 Special case for string literals.
 
StatusCode setProperty (const std::string &name, const std::string &v)
 Special case for std::string.
 
StatusCode setProperty (const std::string &name, const TYPE &value)
 set the property form the value
 
 PropertyHolder ()=default
 
Gaudi::Details::PropertyBasedeclareProperty (Gaudi::Details::PropertyBase &prop)
 Declare a property.
 
Gaudi::Details::PropertyBasedeclareProperty (const std::string &name, TYPE &value, const std::string &doc="none")
 Helper to wrap a regular data member and use it as a regular property.
 
Gaudi::Details::PropertyBasedeclareProperty (const std::string &name, Gaudi::Property< TYPE, VERIFIER, HANDLERS > &prop, const std::string &doc="none")
 Declare a PropertyBase instance setting name and documentation.
 
Gaudi::Details::PropertyBasedeclareRemoteProperty (const std::string &name, IProperty *rsvc, const std::string &rname="")
 Declare a remote property.
 
StatusCode setProperty (const std::string &name, const Gaudi::Details::PropertyBase &p) override
 set the property from another property with a different name
 
StatusCode setProperty (const std::string &s) override
 set the property from the formatted string
 
StatusCode setProperty (const Gaudi::Details::PropertyBase &p)
 Set the property from a property.
 
StatusCode setProperty (const std::string &name, const char *v)
 Special case for string literals.
 
StatusCode setProperty (const std::string &name, const std::string &v)
 Special case for std::string.
 
StatusCode setProperty (const std::string &name, const TYPE &value)
 set the property form the value
 
StatusCode setPropertyRepr (const std::string &n, const std::string &r) override
 set the property from name and value string representation
 
StatusCode getProperty (Gaudi::Details::PropertyBase *p) const override
 get the property
 
const Gaudi::Details::PropertyBasegetProperty (std::string_view name) const override
 get the property by name
 
StatusCode getProperty (std::string_view n, std::string &v) const override
 convert the property to the string
 
const std::vector< Gaudi::Details::PropertyBase * > & getProperties () const override
 get all properties
 
bool hasProperty (std::string_view name) const override
 Return true if we have a property with the given name.
 
Gaudi::Details::PropertyBaseproperty (std::string_view name) const
 \fixme property and bindPropertiesTo should be protected
 
void bindPropertiesTo (Gaudi::Interfaces::IOptionsSvc &optsSvc)
 
 PropertyHolder (const PropertyHolder &)=delete
 
PropertyHolderoperator= (const PropertyHolder &)=delete
 
- Public Member Functions inherited from CommonMessaging< implements< IService, IProperty, IStateful > >
MSG::Level msgLevel () const
 get the cached level (originally extracted from the embedded MsgStream)
 
bool msgLevel (MSG::Level lvl) const
 get the output level from the embedded MsgStream
 
- Public Member Functions inherited from CommonMessagingBase
virtual ~CommonMessagingBase ()=default
 Virtual destructor.
 
const SmartIF< IMessageSvc > & msgSvc () const
 The standard message service.
 
MsgStreammsgStream () const
 Return an uninitialized MsgStream.
 
MsgStreammsgStream (const MSG::Level level) const
 Predefined configurable message stream for the efficient printouts.
 
MsgStreamalways () const
 shortcut for the method msgStream(MSG::ALWAYS)
 
MsgStreamfatal () const
 shortcut for the method msgStream(MSG::FATAL)
 
MsgStreamerr () const
 shortcut for the method msgStream(MSG::ERROR)
 
MsgStreamerror () const
 shortcut for the method msgStream(MSG::ERROR)
 
MsgStreamwarning () const
 shortcut for the method msgStream(MSG::WARNING)
 
MsgStreaminfo () const
 shortcut for the method msgStream(MSG::INFO)
 
MsgStreamdebug () const
 shortcut for the method msgStream(MSG::DEBUG)
 
MsgStreamverbose () const
 shortcut for the method msgStream(MSG::VERBOSE)
 
MsgStreammsg () const
 shortcut for the method msgStream(MSG::INFO)
 

Private Member Functions

StatusCode finalizeTool (IAlgTool *itool) const
 Finalize the given tool, with exception handling.
 

Private Attributes

Gaudi::Property< bool > m_checkNamedToolsConfigured
 
Gaudi::Property< bool > m_showToolDataDeps { this, "ShowDataDeps", false, "show the data dependencies of AlgTools" }
 
Gaudi::Property< std::set< std::string > > m_blessed_public_tools
 
std::recursive_mutex m_mut
 
ToolList m_instancesTools
 
SmartIF< IHistorySvcm_pHistorySvc
 Pointer to HistorySvc.
 
std::vector< IToolSvc::Observer * > m_observers
 

Additional Inherited Members

- Public Types inherited from extends< Service, IToolSvc >
using base_class
 Typedef to this class.
 
using extend_interfaces_base
 Typedef to the base of this class.
 
- Public Types inherited from Service
using Factory = Gaudi::PluginService::Factory<IService*( const std::string&, ISvcLocator* )>
 
- Public Types inherited from PropertyHolder< CommonMessaging< implements< IService, IProperty, IStateful > > >
using PropertyHolderImpl
 Typedef used to refer to this class from derived classes, as in.
 
- Public Types inherited from CommonMessaging< implements< IService, IProperty, IStateful > >
using base_class
 
- Public Types inherited from extend_interfaces< Interfaces... >
using ext_iids
 take union of the ext_iids of all Interfaces...
 
- Protected Member Functions inherited from Service
std::vector< IAlgTool * > & tools ()
 
 ~Service () override
 
int outputLevel () const
 get the Service's output level
 
- Protected Member Functions inherited from CommonMessaging< implements< IService, IProperty, IStateful > >
MSG::Level setUpMessaging () const
 Set up local caches.
 
MSG::Level resetMessaging ()
 Reinitialize internal states.
 
void updateMsgStreamOutputLevel (int level)
 Update the output level of the cached MsgStream.
 
- Protected Attributes inherited from Service
Gaudi::StateMachine::State m_state = Gaudi::StateMachine::OFFLINE
 Service state.
 
Gaudi::StateMachine::State m_targetState = Gaudi::StateMachine::OFFLINE
 Service state.
 
Gaudi::Property< int > m_outputLevel { this, "OutputLevel", MSG::NIL, "output level" }
 flag indicating whether ToolHandle tools have been added to m_tools
 
Gaudi::Property< bool > m_auditorInitialize { this, "AuditInitialize", false, "trigger auditor on initialize()" }
 
Gaudi::Property< bool > m_auditorStart { this, "AuditStart", false, "trigger auditor on start()" }
 
Gaudi::Property< bool > m_auditorStop { this, "AuditStop", false, "trigger auditor on stop()" }
 
Gaudi::Property< bool > m_auditorFinalize { this, "AuditFinalize", false, "trigger auditor on finalize()" }
 
Gaudi::Property< bool > m_auditorReinitialize { this, "AuditReinitialize", false, "trigger auditor on reinitialize()" }
 
Gaudi::Property< bool > m_auditorRestart { this, "AuditRestart", false, "trigger auditor on restart()" }
 
Gaudi::Property< bool > m_autoRetrieveTools
 
Gaudi::Property< bool > m_checkToolDeps
 
SmartIF< IAuditorSvcm_pAuditorSvc
 Auditor Service.
 

Detailed Description

This service manages tools.

Tools can be common, in which case a single instance can be shared by different algorithms, or private in which case it is necessary to specify the parent when requesting it. The parent of a tool can be an algortihm or a Service The environment of a tool is set by using that of the parent. A common tool is considered to belong to the ToolSvc itself.

Author
G. Corti, P. Mato

Definition at line 45 of file ToolSvc.cpp.

Constructor & Destructor Documentation

◆ ~ToolSvc()

ToolSvc::~ToolSvc ( )
override

Definition at line 186 of file ToolSvc.cpp.

186 {
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}
void setUnregister(std::function< void()> unregister)
Definition IToolSvc.h:240
std::vector< IToolSvc::Observer * > m_observers
Definition ToolSvc.cpp:164

Member Function Documentation

◆ create() [1/2]

StatusCode ToolSvc::create ( const std::string & type,
const IInterface * parent,
IAlgTool *& tool )

Create Tool standard way with automatically assigned name.

Definition at line 463 of file ToolSvc.cpp.

463 {
464 const std::string& toolname = tooltype;
465 return create( tooltype, toolname, parent, tool );
466}
StatusCode create(const std::string &type, const IInterface *parent, IAlgTool *&tool)
Create Tool standard way with automatically assigned name.
Definition ToolSvc.cpp:463

◆ create() [2/2]

StatusCode ToolSvc::create ( const std::string & tooltype,
const std::string & toolname,
const IInterface * parent,
IAlgTool *& tool )

Create Tool standard way with specified name.

Now able to handle clones.

The test of tool existence is performed according to three criteria: name, type and parent. If a tool is private, i.e. the parent is not the tool Svc, and it exist but the parent is not the specified one, a clone is handed over. No clones of public tools are allowed since they would be undistinguishable.

invoke create callbacks...

Definition at line 519 of file ToolSvc.cpp.

520 {
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
596 StatusCode sc = StatusCode::FAILURE;
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;
624 Gaudi::Interfaces::IOptionsSvc& joSvc = this->serviceLocator()->getOptsSvc();
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}
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition MsgStream.h:198
#define ON_VERBOSE
Definition ToolSvc.cpp:30
#define ON_DEBUG
Definition ToolSvc.cpp:29
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)
Gaudi::Interfaces::IOptionsSvc & getOptsSvc()
Direct access to Gaudi::Interfaces::IOptionsSvc implementation.
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
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
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
bool existsTool(std::string_view fullname) const
Check if the tool instance exists.
Definition ToolSvc.cpp:679
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
Gaudi::Property< bool > m_checkNamedToolsConfigured
Definition ToolSvc.cpp:99
SmartIF< IHistorySvc > m_pHistorySvc
Pointer to HistorySvc.
Definition ToolSvc.cpp:162
virtual bool isSet(const std::string &key) const =0
Test if an option key was explicitly set or not.

◆ existsTool()

bool ToolSvc::existsTool ( std::string_view fullname) const

Check if the tool instance exists.

Definition at line 679 of file ToolSvc.cpp.

679 {
680 auto lock = std::scoped_lock{ m_mut };
681 return m_instancesTools.contains( fullname );
682}

◆ finalize()

StatusCode ToolSvc::finalize ( )
override

Finalize the service.

Algorithm: 2 passes. First pass:

  • do not explicitly release any tools
  • finalize tools, in the order of increasing number of refCounts Second pass:
  • explicitly release all tools, one release() on all tools per loop. -> tools are deleted in the order of increasing number of refCounts.

Inner loop: full loop over all left-over tools

  • finalize tools with the minimum number of refCounts in the list.
  • Remove finalized tools from list of tools, and add them to the list of finalized tools, to be deleted at the end. This way, any non-finalized tools who still reference already finalized tools in their finalize() will still find a live tool. Outer loop: keep on going until nothing changes in the list of tools. Checking for:
  • number of left-over tools
  • total number of refcounts
  • minimum number of refcounts

Definition at line 192 of file ToolSvc.cpp.

192 {
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}
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
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.
StatusCode finalize() override
Definition Service.cpp:223
const std::vector< IAlgTool * > & tools() const
Definition Service.cpp:411
StatusCode finalizeTool(IAlgTool *itool) const
Finalize the given tool, with exception handling.
Definition ToolSvc.cpp:684

◆ finalizeTool()

StatusCode ToolSvc::finalizeTool ( IAlgTool * itool) const
private

Finalize the given tool, with exception handling.

Definition at line 684 of file ToolSvc.cpp.

684 {
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}
virtual StatusCode sysFinalize()=0
Finalization of the Tool.

◆ getInstances() [1/2]

std::vector< std::string > ToolSvc::getInstances ( ) const
override

Get names of all tool instances.

Definition at line 423 of file ToolSvc.cpp.

423 {
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}

◆ getInstances() [2/2]

std::vector< std::string > ToolSvc::getInstances ( std::string_view toolType)
override

Get names of all tool instances of a given type.

Definition at line 413 of file ToolSvc.cpp.

413 {
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}

◆ getTools()

std::vector< IAlgTool * > ToolSvc::getTools ( ) const
override

Get pointers to all tool instances.

Definition at line 431 of file ToolSvc.cpp.

431 {
432 auto lock = std::scoped_lock{ m_mut };
433 return { std::begin( m_instancesTools ), std::end( m_instancesTools ) };
434}

◆ nameTool()

std::string ToolSvc::nameTool ( std::string_view nameByUser,
const IInterface * parent )

Get Tool full name by combining nameByUser and "parent" part.

Definition at line 663 of file ToolSvc.cpp.

663 {
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}
const std::string & name() const override
Retrieve name of the service.
Definition Service.cpp:333

◆ registerObserver()

void ToolSvc::registerObserver ( IToolSvc::Observer * obs)
override

Definition at line 711 of file ToolSvc.cpp.

711 {
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}

◆ releaseTool()

StatusCode ToolSvc::releaseTool ( IAlgTool * tool)
override

Release tool.

Definition at line 436 of file ToolSvc.cpp.

436 {
437 auto lock = std::scoped_lock{ m_mut };
438 StatusCode sc( StatusCode::SUCCESS );
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}
Gaudi::StateMachine::State m_targetState
Service state.
Definition Service.h:157

◆ retrieve() [1/2]

StatusCode ToolSvc::retrieve ( std::string_view tooltype,
std::string_view toolname,
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.

invoke retrieve callbacks...

Definition at line 358 of file ToolSvc.cpp.

359 {
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}
virtual void const * i_cast(const InterfaceID &) const =0
virtual void onRetrieve(const IAlgTool *)
Definition IToolSvc.h:243
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

◆ retrieve() [2/2]

StatusCode ToolSvc::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 at line 339 of file ToolSvc.cpp.

340 {
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}

◆ start()

StatusCode ToolSvc::start ( )
override

Definition at line 723 of file ToolSvc.cpp.

723 {
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}
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
Gaudi::Property< bool > m_showToolDataDeps
Definition ToolSvc.cpp:103

◆ stop()

StatusCode ToolSvc::stop ( )
override

Definition at line 762 of file ToolSvc.cpp.

762 {
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}

Member Data Documentation

◆ m_blessed_public_tools

Gaudi::Property<std::set<std::string> > ToolSvc::m_blessed_public_tools
private
Initial value:
{
this,
"AllowedPublicTools",
{},
"if non-empty, block the creation of public tools that are not listed in the set" }

Definition at line 105 of file ToolSvc.cpp.

105 {
106 this,
107 "AllowedPublicTools",
108 {},
109 "if non-empty, block the creation of public tools that are not listed in the set" };

◆ m_checkNamedToolsConfigured

Gaudi::Property<bool> ToolSvc::m_checkNamedToolsConfigured
private
Initial value:
{
this, "CheckedNamedToolsConfigured", false,
"Check that tools which do not have the default name have some explicit configuration." }

Definition at line 99 of file ToolSvc.cpp.

99 {
100 this, "CheckedNamedToolsConfigured", false,
101 "Check that tools which do not have the default name have some explicit configuration." };

◆ m_instancesTools

ToolList ToolSvc::m_instancesTools
private

Definition at line 159 of file ToolSvc.cpp.

◆ m_mut

std::recursive_mutex ToolSvc::m_mut
mutableprivate

Definition at line 158 of file ToolSvc.cpp.

◆ m_observers

std::vector<IToolSvc::Observer*> ToolSvc::m_observers
private

Definition at line 164 of file ToolSvc.cpp.

◆ m_pHistorySvc

SmartIF<IHistorySvc> ToolSvc::m_pHistorySvc
private

Pointer to HistorySvc.

Definition at line 162 of file ToolSvc.cpp.

◆ m_showToolDataDeps

Gaudi::Property<bool> ToolSvc::m_showToolDataDeps { this, "ShowDataDeps", false, "show the data dependencies of AlgTools" }
private

Definition at line 103 of file ToolSvc.cpp.

103{ this, "ShowDataDeps", false, "show the data dependencies of AlgTools" };

The documentation for this class was generated from the following file: