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." };
110 std::size_t
operator()(
IAlgTool const* s )
const noexcept {
return std::hash<std::string_view>{}( s->name() ); }
111 std::size_t
operator()( std::string_view s )
const noexcept {
return std::hash<std::string_view>{}( s ); }
119 std::unordered_multiset<IAlgTool*, Hash, Equal>
m_map;
124 auto range =
m_map.equal_range( tool->name() );
125 auto itm = std::find_if( range.first, range.second, [&](
auto const& p ) { return p == tool; } );
126 if ( itm != range.second )
m_map.erase( itm );
130 m_map.emplace( tool );
143 auto it = std::find_if( range.first, range.second, [&](
auto const& p ) { return p->parent() == parent; } );
144 return it != range.second ? *it :
nullptr;
146 std::vector<IAlgTool*>
grab() && {
163 template <
typename C>
164 unsigned long totalRefCount(
const C& toolList ) {
165 return std::accumulate( begin( toolList ), end( toolList ), 0ul,
166 [&](
unsigned long count,
const IAlgTool* tool ) {
return count + tool->refCount(); } );
170 template <
typename C>
171 unsigned long minimumRefCount(
const C& toolList ) {
172 return std::accumulate(
begin( toolList ),
end( toolList ), ~0ul,
173 [](
unsigned long c,
const IAlgTool* tool ) {
return std::min( c,
tool->refCount() ); } );
211 info() <<
"Removing all tools created by ToolSvc" <<
endmsg;
217 log <<
" Tool List : ";
218 for (
const auto& iTool :
tools ) { log << iTool->name() <<
":" << iTool->refCount() <<
" "; }
237 boost::circular_buffer<IAlgTool*> finalizedTools(
tools.size() );
239 size_t toolCount =
tools.size();
240 unsigned long startRefCount = 0;
241 unsigned long endRefCount = totalRefCount(
tools );
242 unsigned long startMinRefCount = 0;
243 unsigned long endMinRefCount = minimumRefCount(
tools );
244 while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
245 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
246 debug() << toolCount <<
" tools left to finalize. Summed refCounts: " << endRefCount <<
endmsg;
247 debug() <<
"Will finalize tools with refCount <= " << endMinRefCount <<
endmsg;
249 startMinRefCount = endMinRefCount;
250 startRefCount = endRefCount;
251 unsigned long maxLoop = toolCount + 1;
252 while ( --maxLoop > 0 && !
tools.empty() ) {
256 unsigned long count = pTool->
refCount();
258 const std::string& toolName = pTool->
name();
259 if ( count <= startMinRefCount ) {
260 ON_DEBUG debug() <<
" Performing finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
268 finalizedTools.push_back( pTool );
272 ON_DEBUG debug() <<
" Delaying finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
276 toolCount =
tools.size();
277 endRefCount = totalRefCount(
tools );
278 endMinRefCount = minimumRefCount(
tools );
294 auto maxLoop = totalRefCount( finalizedTools ) + 1;
295 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
296 IAlgTool* pTool = finalizedTools.front();
297 finalizedTools.pop_front();
304 finalizedTools.push_back( pTool );
311 if ( !
tools.empty() ) {
312 error() <<
"Unable to finalize and delete the following tools : ";
313 for (
const auto& iTool :
tools ) {
error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
318 if ( !finalizedTools.empty() ) {
319 error() <<
"Failed to delete the following " << finalizedTools.size()
320 <<
" finalized tools. Bug in ToolSvc::finalize()?: ";
321 for (
const auto& iTool : finalizedTools ) {
error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
330 constexpr std::string_view s_PUBLIC =
":PUBLIC";
336 if ( tooltype.ends_with( s_PUBLIC ) ) {
338 tooltype.remove_suffix( s_PUBLIC.size() );
339 return retrieve( tooltype, iid, tool,
this, createIf );
343 if ( tooltype.empty() ) {
344 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
347 auto pos = tooltype.find(
'/' );
348 if ( std::string_view::npos == pos ) {
return retrieve( tooltype, tooltype, iid, tool, parent, createIf ); }
349 return retrieve( tooltype.substr( 0, pos ), tooltype.substr( pos + 1 ), iid, tool, parent, createIf );
356 if ( toolname.empty() || ( std::string_view::npos != tooltype.find(
'/' ) ) ) {
357 return retrieve( tooltype, iid, tool, parent, createIf );
361 if ( toolname.ends_with( s_PUBLIC ) ) {
363 toolname.remove_suffix( s_PUBLIC.size() );
364 return retrieve( tooltype, toolname, iid, tool,
this, createIf );
372 if ( !parent ) parent =
this;
373 const std::string fullname =
nameTool( toolname, parent );
377 auto lock = std::scoped_lock{
m_mut };
379 if ( itool ) {
ON_DEBUG debug() <<
"Retrieved tool " << toolname <<
" with parent " << parent <<
endmsg; }
385 warning() <<
"Tool " << toolname <<
" not found and creation not requested" <<
endmsg;
388 sc =
create( std::string{ tooltype }, std::string{ toolname }, parent, itool );
395 error() <<
"Tool " << toolname <<
" either does not implement the correct interface, or its version is incompatible"
410 std::vector<std::string>
tools;
411 auto lock = std::scoped_lock{
m_mut };
413 if ( tool->type() == toolType )
tools.push_back( tool->name() );
419 auto lock = std::scoped_lock{
m_mut };
422 [](
const IAlgTool* t ) {
return t->name(); } );
427 auto lock = std::scoped_lock{
m_mut };
432 auto lock = std::scoped_lock{
m_mut };
436 unsigned long count = tool->refCount();
443 debug() <<
" Performing finalization of " << tool->name() <<
" (refCount " << count <<
")" <<
endmsg;
445 debug() <<
" Performing deletion of " << tool->name() <<
endmsg;
447 debug() <<
"Performing finalization and deletion of " << tool->name() <<
endmsg;
459 const std::string& toolname = tooltype;
460 return create( tooltype, toolname, parent, tool );
466 template <
typename T>
467 class ToolCreateGuard {
471 std::unique_ptr<IAlgTool> m_tool;
474 explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
478 ToolCreateGuard( ToolCreateGuard&& ) noexcept = default;
480 void create( const std::
string& tooltype, const std::
string& fullname, const IInterface* parent ) {
482 if ( m_tool ) { m_tools.remove( m_tool.get() ); };
483 m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
485 if ( m_tool ) { m_tools.push_back( m_tool.get() ); }
488 IAlgTool*
get() {
return m_tool.get(); }
489 IAlgTool* operator->()
const {
494 IAlgTool*
release() {
return m_tool.release(); }
497 if ( m_tool ) m_tools.remove( m_tool.get() );
501 template <
typename C>
502 ToolCreateGuard<C> make_toolCreateGuard( C& c ) {
503 return ToolCreateGuard<C>{
c };
518 if ( tooltype.empty() ) {
519 error() <<
"create(): No Tool Type given" <<
endmsg;
524 if ( !parent ) parent =
this;
529 auto lock = std::scoped_lock{
m_mut };
533 std::string fullname =
nameTool( toolname, parent );
537 if ( iAlgTool->name() == toolname && iAlgTool->parent() == parent ) {
540 error() <<
"Tool " << fullname <<
" already exists with the same parent" <<
endmsg;
541 if ( parent ==
this )
542 error() <<
"... In addition, the parent is the ToolSvc: public tools cannot be cloned!" <<
endmsg;
551 toolguard.create( tooltype, fullname, parent );
552 if ( !toolguard.get() ) {
553 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
558 fatal() <<
"Exception with tag=" << Exception.tag() <<
" is caught whilst instantiating tool '" << tooltype <<
"'"
564 }
catch (
const std::exception& Exception ) {
566 fatal() <<
"Standard std::exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
573 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
587 sc = toolguard->sysInitialize();
591 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst initializing tool '" << fullname <<
"'"
594 }
catch (
const std::exception& Exception ) {
595 error() <<
"Standard std::exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg
596 << Exception.what() <<
endmsg;
599 error() <<
"UNKNOWN Exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg;
605 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
611 if ( toolname != tooltype ) {
612 bool propsSet =
false;
616 bool isSet = joSvc.
isSet( mytool->
name() +
"." + prop->name() );
617 if ( isSet ) propsSet =
true;
620 warning() << tooltype <<
"/" << fullname
621 <<
" : Explicitly named tools should be configured! (assigned name=" << toolname <<
", default is "
622 << tooltype <<
")" <<
endmsg;
629 sc = toolguard->sysStart();
632 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
639 tool = toolguard.release();
654 if ( !parent ) {
return std::string{ this->
name() }.append(
"." ).append( toolname ); }
658 if ( named_parent ) {
659 auto fullname = std::string{ named_parent->name() }.append(
"." ).append( toolname );
663 error() <<
"Private Tools only allowed for components implementing INamedInterface" <<
endmsg;
665 return std::string{
"." }.append( toolname );
669 auto lock = std::scoped_lock{
m_mut };
676 const auto& toolName = itool->
name();
685 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst finalizing tool '" << toolName <<
"'"
688 }
catch (
const std::exception& Exception ) {
689 error() <<
"Standard std::exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg
690 << Exception.what() <<
endmsg;
693 error() <<
"UNKNOWN Exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg;
703 auto lock = std::scoped_lock{
m_mut };
705 auto lock = std::scoped_lock{
m_mut };
717 info() <<
"Listing Data Dependencies of all Tools";
721 std::ostringstream ost;
722 for (
auto& dh : idh->
inputHandles() ) { ost <<
"\n INPUT " << dh->fullKey(); }
723 for (
auto&
id : idh->
extraInputDeps() ) { ost <<
"\n EXTRA INPUT " << id; }
724 for (
auto& dh : idh->
outputHandles() ) { ost <<
"\n OUTPUT " << dh->fullKey(); }
725 for (
auto&
id : idh->
extraOutputDeps() ) { ost <<
"\n EXTRA OUTPUT " << id; }
726 if ( ost.str().length() > 0 ) {
info() <<
"\n" << iTool->name() << ost.str(); }
728 error() <<
"can't cast " << iTool->name() <<
" to IDataHandleHolder!" <<
endmsg;
738 if ( !iTool->sysStart().isSuccess() ) {
740 error() << iTool->name() <<
" failed to start()" <<
endmsg;
745 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
759 if ( !iTool->sysStop().isSuccess() ) {
761 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
766 error() <<
"One or more AlgTools failed to stop()" <<
endmsg;
DEST ** pp_cast(SRC **ptr)
Small function to be used instead of the construct (void**)&pointer, which produces,...
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 StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.
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.