20#include <boost/circular_buffer.hpp>
29#define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
30#define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
48 using extends::extends;
63 bool createIf )
override;
67 const IInterface* parent,
bool createIf )
override;
70 std::vector<std::string>
getInstances( std::string_view toolType )
override;
76 std::vector<IAlgTool*>
getTools()
const override;
88 bool existsTool( std::string_view fullname )
const;
100 this,
"CheckedNamedToolsConfigured",
false,
101 "Check that tools which do not have the default name have some explicit configuration." };
107 "AllowedPublicTools",
109 "if non-empty, block the creation of public tools that are not listed in the set" };
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 ); }
125 std::unordered_multiset<IAlgTool*, Hash, Equal>
m_map;
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 );
136 m_map.emplace( tool );
149 auto it = std::find_if( range.first, range.second, [&](
auto const& p ) { return p->parent() == parent; } );
150 return it != range.second ? *it :
nullptr;
152 std::vector<IAlgTool*>
grab() && {
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(); } );
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() ); } );
217 info() <<
"Removing all tools created by ToolSvc" <<
endmsg;
223 log <<
" Tool List : ";
224 for (
const auto& iTool :
tools ) { log << iTool->name() <<
":" << iTool->refCount() <<
" "; }
243 boost::circular_buffer<IAlgTool*> finalizedTools(
tools.size() );
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;
255 startMinRefCount = endMinRefCount;
256 startRefCount = endRefCount;
257 unsigned long maxLoop = toolCount + 1;
258 while ( --maxLoop > 0 && !
tools.empty() ) {
262 unsigned long count = pTool->
refCount();
264 const std::string& toolName = pTool->
name();
265 if ( count <= startMinRefCount ) {
266 ON_DEBUG debug() <<
" Performing finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
274 finalizedTools.push_back( pTool );
278 ON_DEBUG debug() <<
" Delaying finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
282 toolCount =
tools.size();
283 endRefCount = totalRefCount(
tools );
284 endMinRefCount = minimumRefCount(
tools );
300 auto maxLoop = totalRefCount( finalizedTools ) + 1;
301 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
302 IAlgTool* pTool = finalizedTools.front();
303 finalizedTools.pop_front();
310 finalizedTools.push_back( pTool );
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() <<
" "; }
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() <<
" "; }
336 constexpr std::string_view s_PUBLIC =
":PUBLIC";
342 if ( tooltype.ends_with( s_PUBLIC ) ) {
344 tooltype.remove_suffix( s_PUBLIC.size() );
345 return retrieve( tooltype, iid, tool,
this, createIf );
349 if ( tooltype.empty() ) {
350 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
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 );
362 if ( toolname.empty() || ( std::string_view::npos != tooltype.find(
'/' ) ) ) {
363 return retrieve( tooltype, iid, tool, parent, createIf );
367 if ( toolname.ends_with( s_PUBLIC ) ) {
369 toolname.remove_suffix( s_PUBLIC.size() );
370 return retrieve( tooltype, toolname, iid, tool,
this, createIf );
376 if ( !parent ) parent =
this;
377 const std::string fullname =
nameTool( toolname, parent );
381 auto lock = std::scoped_lock{
m_mut };
383 if ( itool ) {
ON_DEBUG debug() <<
"Retrieved tool " << toolname <<
" with parent " << parent <<
endmsg; }
389 warning() <<
"Tool " << toolname <<
" not found and creation not requested" <<
endmsg;
392 auto sc =
create( std::string{ tooltype }, std::string{ toolname }, parent, itool );
393 if ( sc.isFailure() ) {
return sc; }
399 error() <<
"Tool " << toolname <<
" either does not implement the correct interface, or its version is incompatible"
415 std::vector<std::string>
tools;
416 auto lock = std::scoped_lock{
m_mut };
418 if ( tool->type() == toolType )
tools.push_back( tool->name() );
424 auto lock = std::scoped_lock{
m_mut };
427 [](
const IAlgTool* t ) {
return t->name(); } );
432 auto lock = std::scoped_lock{
m_mut };
437 auto lock = std::scoped_lock{
m_mut };
441 unsigned long count = tool->refCount();
448 debug() <<
" Performing finalization of " << tool->name() <<
" (refCount " << count <<
")" <<
endmsg;
450 debug() <<
" Performing deletion of " << tool->name() <<
endmsg;
452 debug() <<
"Performing finalization and deletion of " << tool->name() <<
endmsg;
464 const std::string& toolname = tooltype;
465 return create( tooltype, toolname, parent, tool );
471 template <
typename T>
472 class ToolCreateGuard {
476 std::unique_ptr<IAlgTool> m_tool;
479 explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
483 ToolCreateGuard( ToolCreateGuard&& ) noexcept = default;
485 void create( const std::
string& tooltype, const std::
string& fullname, const IInterface* parent ) {
487 if ( m_tool ) { m_tools.remove( m_tool.get() ); };
488 m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
490 if ( m_tool ) { m_tools.push_back( m_tool.get() ); }
493 IAlgTool*
get() {
return m_tool.get(); }
494 IAlgTool* operator->()
const {
499 IAlgTool*
release() {
return m_tool.release(); }
502 if ( m_tool ) m_tools.remove( m_tool.get() );
506 template <
typename C>
507 ToolCreateGuard<C> make_toolCreateGuard( C& c ) {
508 return ToolCreateGuard<C>{
c };
523 if ( tooltype.empty() ) {
524 error() <<
"create(): No Tool Type given" <<
endmsg;
529 if ( !parent ) parent =
this;
534 auto lock = std::scoped_lock{
m_mut };
538 std::string fullname =
nameTool( toolname, parent );
542 if ( iAlgTool->name() == toolname && iAlgTool->parent() == parent ) {
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;
556 error() <<
"Tool " << fullname <<
" is not in the list of allowed public tools" <<
endmsg;
562 toolguard.create( tooltype, fullname, parent );
563 if ( !toolguard.get() ) {
564 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
569 fatal() <<
"Exception with tag=" << Exception.tag() <<
" is caught whilst instantiating tool '" << tooltype <<
"'"
575 }
catch (
const std::exception& Exception ) {
577 fatal() <<
"Standard std::exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
584 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
598 sc = toolguard->sysInitialize();
602 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst initializing tool '" << fullname <<
"'"
605 }
catch (
const std::exception& Exception ) {
606 error() <<
"Standard std::exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg
607 << Exception.what() <<
endmsg;
610 error() <<
"UNKNOWN Exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg;
616 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
622 if ( toolname != tooltype ) {
623 bool propsSet =
false;
627 bool isSet = joSvc.
isSet( mytool->
name() +
"." + prop->name() );
628 if ( isSet ) propsSet =
true;
631 warning() << tooltype <<
"/" << fullname
632 <<
" : Explicitly named tools should be configured! (assigned name=" << toolname <<
", default is "
633 << tooltype <<
")" <<
endmsg;
640 sc = toolguard->sysStart();
643 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
650 tool = toolguard.release();
665 if ( !parent ) {
return std::string{ this->
name() }.append(
"." ).append( toolname ); }
669 if ( named_parent ) {
670 auto fullname = std::string{ named_parent->name() }.append(
"." ).append( toolname );
674 error() <<
"Private Tools only allowed for components implementing INamedInterface" <<
endmsg;
676 return std::string{
"." }.append( toolname );
680 auto lock = std::scoped_lock{
m_mut };
687 const auto& toolName = itool->
name();
696 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst finalizing tool '" << toolName <<
"'"
699 }
catch (
const std::exception& Exception ) {
700 error() <<
"Standard std::exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg
701 << Exception.what() <<
endmsg;
704 error() <<
"UNKNOWN Exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg;
714 auto lock = std::scoped_lock{
m_mut };
716 auto lock = std::scoped_lock{
m_mut };
728 info() <<
"Listing Data Dependencies of all Tools";
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(); }
739 error() <<
"can't cast " << iTool->name() <<
" to IDataHandleHolder!" <<
endmsg;
749 if ( !iTool->sysStart().isSuccess() ) {
751 error() << iTool->name() <<
" failed to start()" <<
endmsg;
756 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
770 if ( !iTool->sysStop().isSuccess() ) {
772 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
777 error() <<
"One or more AlgTools failed to stop()" <<
endmsg;
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
#define DECLARE_COMPONENT(type)
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.
Define general base for Gaudi exception.
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.
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.
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.
StatusCode finalize() override
const std::string & name() const override
Retrieve name of the service.
Gaudi::StateMachine::State m_targetState
Service state.
Gaudi::StateMachine::State m_state
Service state.
SmartIF< IFace > service(const std::string &name, bool createIf=true) const
const std::vector< IAlgTool * > & tools() const
Small smart pointer class with automatic reference counting for IInterface.
This class is used for returning status codes from appropriate routines.
constexpr static const auto SUCCESS
constexpr static const auto FAILURE
Base class used to extend a class implementing other interfaces.
AttribStringParser::Iterator begin(const AttribStringParser &parser)
get
decorate the vector of properties
Interface for a component that manages application configuration options.
virtual bool isSet(const std::string &key) const =0
Test if an option key was explicitly set or not.