10 #include "boost/algorithm/string/erase.hpp" 11 #include "boost/algorithm/string/predicate.hpp" 12 #include "boost/circular_buffer.hpp" 19 namespace ba = boost::algorithm;
21 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) ) 22 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) ) 27 unsigned long totalRefCount(
const C& toolList )
31 [&](
unsigned long count,
const IAlgTool* tool ) {
return count + tool->
refCount(); } );
36 void remove( C&
c,
typename C::const_reference i ) {
59 error() <<
"Unable to initialize the Service" <<
endmsg;
64 if (
UNLIKELY( setProperties().isFailure() ) ) {
65 error() <<
"Unable to set base properties" <<
endmsg;
100 info() <<
"Removing all tools created by ToolSvc" <<
endmsg;
105 log <<
" Tool List : ";
106 for (
const auto& iTool : m_instancesTools ) {
log << iTool->name() <<
":" << iTool->refCount() <<
" "; }
125 boost::circular_buffer<IAlgTool*> finalizedTools( m_instancesTools.size() );
127 size_t toolCount = m_instancesTools.size();
128 unsigned long startRefCount = 0;
129 unsigned long endRefCount = totalToolRefCount();
130 unsigned long startMinRefCount = 0;
131 unsigned long endMinRefCount = minimumToolRefCount();
132 while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
133 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
134 debug() << toolCount <<
" tools left to finalize. Summed refCounts: " << endRefCount <<
endmsg;
135 debug() <<
"Will finalize tools with refCount <= " << endMinRefCount <<
endmsg;
137 startMinRefCount = endMinRefCount;
138 startRefCount = endRefCount;
139 unsigned long maxLoop = toolCount + 1;
140 while ( --maxLoop > 0 && !m_instancesTools.empty() ) {
141 IAlgTool* pTool = m_instancesTools.back();
143 m_instancesTools.pop_back();
144 unsigned long count = pTool->
refCount();
147 if ( count <= startMinRefCount ) {
148 ON_DEBUG debug() <<
" Performing finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
151 if ( !finalizeTool( pTool ).isSuccess() ) {
152 warning() <<
" FAILURE finalizing " << toolName <<
endmsg;
156 finalizedTools.push_back( pTool );
160 ON_DEBUG debug() <<
" Delaying finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
161 m_instancesTools.insert(
std::begin( m_instancesTools ), pTool );
164 toolCount = m_instancesTools.size();
165 endRefCount = totalToolRefCount();
166 endMinRefCount = minimumToolRefCount();
181 ON_DEBUG debug() <<
"Deleting " << finalizedTools.size() <<
" finalized tools" <<
endmsg;
182 auto maxLoop = totalRefCount( finalizedTools ) + 1;
183 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
184 IAlgTool* pTool = finalizedTools.front();
185 finalizedTools.pop_front();
192 finalizedTools.push_back( pTool );
199 if ( !m_instancesTools.empty() ) {
200 error() <<
"Unable to finalize and delete the following tools : ";
201 for (
const auto& iTool : m_instancesTools ) { error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
206 if ( !finalizedTools.empty() ) {
207 error() <<
"Failed to delete the following " << finalizedTools.size()
208 <<
" finalized tools. Bug in ToolSvc::finalize()?: ";
209 for (
const auto& iTool : finalizedTools ) { error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
213 if ( m_pHistorySvc ) m_pHistorySvc->release();
234 if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
236 return retrieve( ba::erase_tail_copy( tooltype, s_PUBLIC.
size() ), iid, tool,
this, createIf );
240 if ( tooltype.
empty() ) {
241 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
244 auto pos = tooltype.
find(
'/' );
245 if ( std::string::npos == pos ) {
return retrieve( tooltype, tooltype, iid, tool, parent, createIf ); }
246 return retrieve( tooltype.
substr( 0, pos ), tooltype.
substr( pos + 1 ), iid, tool, parent, createIf );
258 if ( toolname.
empty() || ( std::string::npos != tooltype.
find(
'/' ) ) ) {
259 return retrieve( tooltype, iid, tool, parent, createIf );
263 if ( ba::ends_with( toolname, s_PUBLIC ) ) {
265 return retrieve( tooltype, ba::erase_tail_copy( toolname, s_PUBLIC.
size() ), iid, tool,
this, createIf );
276 if ( !parent ) parent =
this;
277 const std::string fullname = nameTool( toolname, parent );
282 [&](
const IAlgTool* i ) {
return i->
name() == fullname && i->
parent() == parent; } );
283 if ( it !=
std::end( m_instancesTools ) ) {
284 ON_DEBUG debug() <<
"Retrieved tool " << toolname <<
" with parent " << parent <<
endmsg;
292 warning() <<
"Tool " << toolname <<
" not found and creation not requested" <<
endmsg;
295 sc = create( tooltype, toolname, parent, itool );
302 error() <<
"Tool " << toolname <<
" either does not implement the correct interface, or its version is incompatible" 321 for (
const auto& tool : m_instancesTools ) {
322 if ( tool->type() == toolType ) tools.
push_back( tool->name() );
350 if ( m_instancesTools.rend() !=
std::find( m_instancesTools.rbegin(), m_instancesTools.rend(), tool ) ) {
351 unsigned long count = tool->
refCount();
358 debug() <<
" Performing finalization of " << tool->
name() <<
" (refCount " << count <<
")" <<
endmsg;
360 debug() <<
" Performing deletion of " << tool->
name() <<
endmsg;
362 debug() <<
"Performing finalization and deletion of " << tool->
name() <<
endmsg;
364 sc = finalizeTool( tool );
366 remove( m_instancesTools, tool );
378 return create( tooltype, toolname, parent, tool );
384 template <
typename T>
385 class ToolCreateGuard {
392 explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
396 ToolCreateGuard( ToolCreateGuard&& ) noexcept =
default;
400 if ( m_tool )
remove( m_tools, m_tool.
get() );
401 m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
403 if ( m_tool ) m_tools.push_back( m_tool.
get() );
415 if ( m_tool )
remove( m_tools, m_tool.
get() );
419 template <
typename C>
420 ToolCreateGuard<C> make_toolCreateGuard( C&
c ) {
421 return ToolCreateGuard<C>{c};
441 error() <<
"create(): No Tool Type given" <<
endmsg;
446 if ( !parent ) parent =
this;
451 auto toolguard = make_toolCreateGuard( m_instancesTools );
454 std::string fullname = nameTool( toolname, parent );
455 if (
UNLIKELY( existsTool( fullname ) ) ) {
461 error() <<
"Tool " << fullname <<
" already exists with the same parent" <<
endmsg;
462 if ( parent ==
this )
463 error() <<
"... In addition, the parent is the ToolSvc: public tools cannot be cloned!" <<
endmsg;
472 toolguard.create( tooltype, fullname, parent );
473 if (
UNLIKELY( !toolguard.get() ) ) {
474 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
479 fatal() <<
"Exception with tag=" << Exception.
tag() <<
" is caught whilst instantiating tool '" << tooltype <<
"'" 483 fatal() << Exception <<
endmsg;
487 fatal() <<
"Standard std::exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
494 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
506 error() <<
"Error setting properties for tool '" << fullname <<
"'" <<
endmsg;
514 sc = toolguard->sysInitialize();
518 error() <<
"GaudiException with tag=" << Exception.
tag() <<
" caught whilst initializing tool '" << fullname <<
"'" 519 << endmsg << Exception <<
endmsg;
522 error() <<
"Standard std::exception caught whilst initializing tool '" << fullname <<
"'" << endmsg
526 error() <<
"UNKNOWN Exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg;
532 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
538 sc = toolguard->sysStart();
541 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
556 if ( m_pHistorySvc || service(
"HistorySvc", m_pHistorySvc,
false ).isSuccess() ) {
557 m_pHistorySvc->registerAlgTool( *tool ).ignore();
567 if ( !parent ) {
return this->
name() +
"." +
toolname; }
571 if ( named_parent ) {
572 auto fullname = named_parent->name() +
"." +
toolname;
576 error() <<
"Private Tools only allowed for components implementing INamedInterface" <<
endmsg;
587 [&](
const IAlgTool* tool ) {
return tool->
name() == fullname; } );
588 return i !=
std::end( m_instancesTools );
602 sc = itool->sysFinalize();
606 error() <<
"GaudiException with tag=" << Exception.
tag() <<
" caught whilst finalizing tool '" << toolName <<
"'" 610 error() <<
"Standard std::exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg 614 error() <<
"UNKNOWN Exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg;
625 return totalRefCount( m_instancesTools );
634 return i !=
std::end( m_instancesTools ) ? ( *i )->refCount() : 0;
645 auto i =
std::find( m_observers.begin(), m_observers.end(), obs );
646 if ( i != m_observers.end() ) m_observers.erase( i );
648 m_observers.push_back( obs );
659 for (
auto& iTool : m_instancesTools ) {
662 if (
UNLIKELY( !iTool->sysStart().isSuccess() ) ) {
664 error() << iTool->name() <<
" failed to start()" <<
endmsg;
669 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
683 for (
auto& iTool : m_instancesTools ) {
686 if (
UNLIKELY( !iTool->sysStop().isSuccess() ) ) {
688 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
693 error() <<
"One or more AlgTools failed to stop()" <<
endmsg;
StatusCode initialize() override
Define general base for Gaudi exception.
StatusCode finalize() override
constexpr static const auto SUCCESS
#define DECLARE_COMPONENT(type)
This class is used for returning status codes from appropriate routines.
Definition of the basic interface.
virtual const std::string & tag() const
name tag for the exception, or exception type
virtual unsigned long release()=0
Release Interface instance.
constexpr static const auto FAILURE
virtual unsigned long refCount() const =0
Current reference count.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
virtual const std::string & name() const =0
Retrieve the name of the instance.
virtual StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.