16 #include "boost/circular_buffer.hpp" 17 #include "boost/algorithm/string/predicate.hpp" 18 #include "boost/algorithm/string/erase.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 ) {
37 template <
typename C>
void remove(C&
c,
typename C::const_reference i) {
61 error() <<
"Unable to initialize the Service" <<
endmsg;
66 if (
UNLIKELY(setProperties().isFailure())) {
67 error() <<
"Unable to set base properties" <<
endmsg;
102 info() <<
"Removing all tools created by ToolSvc" <<
endmsg;
107 log <<
" Tool List : ";
108 for (
const auto& iTool : m_instancesTools ) {
109 log << iTool->name() <<
":" << iTool->refCount( ) <<
" ";
129 boost::circular_buffer<IAlgTool*> finalizedTools(m_instancesTools.size());
131 size_t toolCount = m_instancesTools.size();
132 unsigned long startRefCount = 0;
133 unsigned long endRefCount = totalToolRefCount();
134 unsigned long startMinRefCount = 0;
135 unsigned long endMinRefCount = minimumToolRefCount();
136 while ( toolCount > 0 &&
138 (endRefCount != startRefCount || endMinRefCount != startMinRefCount) ) {
139 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
140 debug() << toolCount <<
" tools left to finalize. Summed refCounts: " 142 debug() <<
"Will finalize tools with refCount <= " 143 << endMinRefCount <<
endmsg;
145 startMinRefCount = endMinRefCount;
146 startRefCount = endRefCount;
147 unsigned long maxLoop = toolCount + 1;
148 while ( --maxLoop > 0 && !m_instancesTools.empty() ) {
149 IAlgTool* pTool = m_instancesTools.back();
151 m_instancesTools.pop_back();
152 unsigned long count = pTool->
refCount( );
155 if ( count <= startMinRefCount ) {
156 ON_DEBUG debug() <<
" Performing finalization of " << toolName
157 <<
" (refCount " << count <<
")" <<
endmsg;
160 if (!finalizeTool(pTool).isSuccess()) {
161 warning() <<
" FAILURE finalizing " << toolName <<
endmsg;
165 finalizedTools.push_back(pTool);
169 ON_DEBUG debug() <<
" Delaying finalization of " << toolName
170 <<
" (refCount " << count <<
")" <<
endmsg;
171 m_instancesTools.insert(
std::begin(m_instancesTools), pTool );
174 toolCount = m_instancesTools.size();
175 endRefCount = totalToolRefCount();
176 endMinRefCount = minimumToolRefCount();
191 ON_DEBUG debug() <<
"Deleting " << finalizedTools.size() <<
" finalized tools" <<
endmsg;
192 auto maxLoop = totalRefCount( finalizedTools ) + 1;
193 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
194 IAlgTool* pTool = finalizedTools.front();
195 finalizedTools.pop_front();
201 <<
" (refCount " << count <<
")" <<
endmsg;
203 finalizedTools.push_back(pTool);
210 if ( !m_instancesTools.empty() ) {
211 error() <<
"Unable to finalize and delete the following tools : ";
212 for (
const auto& iTool : m_instancesTools ) {
213 error() << iTool->name() <<
": " << iTool->refCount( ) <<
" ";
219 if ( !finalizedTools.empty() ) {
220 error() <<
"Failed to delete the following " << finalizedTools.size()
221 <<
" finalized tools. Bug in ToolSvc::finalize()?: ";
222 for (
const auto& iTool : finalizedTools ) {
223 error() << iTool->name() <<
": " << iTool->refCount( ) <<
" ";
228 if ( m_pHistorySvc ) m_pHistorySvc->release();
256 if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
258 return retrieve ( ba::erase_tail_copy(tooltype, s_PUBLIC.
size()),
259 iid , tool ,
this , createIf ) ;
263 if ( tooltype.
empty() ) {
264 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
267 auto pos = tooltype.
find(
'/');
268 if ( std::string::npos == pos ) {
269 return retrieve ( tooltype , tooltype , iid , tool , parent , createIf );
271 return retrieve ( tooltype.
substr( 0 , pos ),
272 tooltype.
substr( pos + 1 ),
273 iid , tool , parent , createIf ) ;
289 if( toolname.
empty() || (std::string::npos != tooltype.
find(
'/')) )
290 {
return retrieve ( tooltype , iid , tool , parent , createIf ) ; }
293 if ( ba::ends_with( toolname, s_PUBLIC ) )
296 return retrieve ( tooltype , ba::erase_tail_copy(toolname, s_PUBLIC.
size() ),
297 iid , tool ,
this , createIf ) ;
308 if( !parent ) parent =
this;
309 const std::string fullname = nameTool( toolname, parent );
315 return i->
name() == fullname && i->
parent() == parent;
317 if (it!=
std::end(m_instancesTools)) {
318 ON_DEBUG debug() <<
"Retrieved tool " << toolname <<
" with parent " << parent <<
endmsg;
326 warning() <<
"Tool " << toolname
327 <<
" not found and creation not requested" <<
endmsg;
330 sc = create( tooltype, toolname, parent, itool );
337 error() <<
"Tool " << toolname
338 <<
" either does not implement the correct interface, or its version is incompatible" 358 for(
const auto& tool: m_instancesTools) {
359 if (tool->type() == toolType) tools.
push_back( tool->name() );
388 if ( m_instancesTools.rend() !=
std::find( m_instancesTools.rbegin(),
389 m_instancesTools.rend(),
391 unsigned long count = tool->
refCount();
398 debug() <<
" Performing finalization of " << tool->
name()
399 <<
" (refCount " << count <<
")" <<
endmsg;
401 debug() <<
" Performing deletion of " << tool->
name() <<
endmsg;
403 debug() <<
"Performing finalization and deletion of " << tool->
name() <<
endmsg;
405 sc = finalizeTool(tool);
407 remove(m_instancesTools,tool);
421 return create( tooltype, toolname, parent, tool);
427 template <
typename T>
428 class ToolCreateGuard {
435 explicit ToolCreateGuard(T& tools): m_tools(tools) {}
439 ToolCreateGuard(ToolCreateGuard&&) noexcept =
default;
443 if (m_tool)
remove(m_tools,m_tool.
get());
444 m_tool.
reset(AlgTool::Factory::create(tooltype, tooltype, fullname, parent)) ;
446 if (m_tool) m_tools.push_back(m_tool.
get());
462 if (m_tool)
remove(m_tools,m_tool.
get());
466 template <
typename C>
467 ToolCreateGuard<C> make_toolCreateGuard(C&
c) {
468 return ToolCreateGuard<C>{ c };
490 error() <<
"create(): No Tool Type given" <<
endmsg;
495 if ( !parent ) parent =
this;
500 auto toolguard = make_toolCreateGuard(m_instancesTools);
504 if(
UNLIKELY(existsTool(fullname)) ) {
510 error() <<
"Tool " << fullname <<
" already exists with the same parent" <<
endmsg;
512 error() <<
"... In addition, the parent is the ToolSvc: public tools cannot be cloned!" <<
endmsg;
521 toolguard.create( tooltype, fullname, parent );
523 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
529 fatal() <<
"Exception with tag=" << Exception.
tag()
530 <<
" is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
533 fatal() << Exception <<
endmsg;
538 fatal() <<
"Standard std::exception is caught whilst instantiating tool '" 539 << tooltype <<
"'" <<
endmsg;
547 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '" 548 << tooltype <<
"'" <<
endmsg;
560 error() <<
"Error setting properties for tool '" 561 << fullname <<
"'" <<
endmsg;
569 sc = toolguard->sysInitialize();
575 <<
"GaudiException with tag=" << Exception.
tag()
576 <<
" caught whilst initializing tool '" << fullname <<
"'" << endmsg
583 <<
"Standard std::exception caught whilst initializing tool '" 584 << fullname <<
"'" << endmsg << Exception.
what() <<
endmsg;
590 <<
"UNKNOWN Exception caught whilst initializing tool '" 591 << fullname <<
"'" <<
endmsg;
597 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
603 sc = toolguard->sysStart();
606 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
624 if (m_pHistorySvc || service(
"HistorySvc",m_pHistorySvc,
false).isSuccess() ) {
625 m_pHistorySvc->registerAlgTool(*tool).ignore();
637 if ( !parent ) {
return this->
name() +
"." +
toolname; }
643 auto fullname = named_parent->name() +
"." +
toolname ;
647 error() <<
"Private Tools only allowed for components implementing INamedInterface" 659 [&](
const IAlgTool* tool) {
return tool->
name() == fullname; } );
660 return i !=
std::end(m_instancesTools);
674 sc = itool->sysFinalize();
680 <<
"GaudiException with tag=" << Exception.
tag()
681 <<
" caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg 688 <<
"Standard std::exception caught whilst finalizing tool '" 695 <<
"UNKNOWN Exception caught whilst finalizing tool '" 696 << toolName <<
"'" <<
endmsg;
708 return totalRefCount( m_instancesTools );
718 return i!=
std::end(m_instancesTools) ? (*i)->refCount() : 0;
727 m_observers.push_back(obs);
733 auto i =
std::find(m_observers.begin(),m_observers.end(),obs);
734 if (i!=m_observers.end()) m_observers.erase(i);
746 for (
auto& iTool : m_instancesTools ) {
749 if (
UNLIKELY(!iTool->sysStart().isSuccess())) {
751 error() << iTool->name() <<
" failed to start()" <<
endmsg;
757 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
772 for (
auto& iTool : m_instancesTools ) {
775 if (
UNLIKELY(!iTool->sysStop().isSuccess())) {
777 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
783 error() <<
"One or more AlgTools failed to stop()" <<
endmsg;
StatusCode initialize() override
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
StatusCode finalize() override
bool isFailure() const
Test for a status code of FAILURE.
#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.
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.