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) {
69 error() <<
"Unable to initialize the Service" <<
endmsg;
74 if (
UNLIKELY(setProperties().isFailure())) {
75 error() <<
"Unable to set base properties" <<
endmsg;
110 info() <<
"Removing all tools created by ToolSvc" <<
endmsg;
115 log <<
" Tool List : ";
116 for (
const auto& iTool : m_instancesTools ) {
117 log << iTool->name() <<
":" << iTool->refCount( ) <<
" ";
137 boost::circular_buffer<IAlgTool*> finalizedTools(m_instancesTools.size());
139 size_t toolCount = m_instancesTools.size();
140 unsigned long startRefCount = 0;
141 unsigned long endRefCount = totalToolRefCount();
142 unsigned long startMinRefCount = 0;
143 unsigned long endMinRefCount = minimumToolRefCount();
144 while ( toolCount > 0 &&
146 (endRefCount != startRefCount || endMinRefCount != startMinRefCount) ) {
147 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
148 debug() << toolCount <<
" tools left to finalize. Summed refCounts: " 150 debug() <<
"Will finalize tools with refCount <= " 151 << endMinRefCount <<
endmsg;
153 startMinRefCount = endMinRefCount;
154 startRefCount = endRefCount;
155 unsigned long maxLoop = toolCount + 1;
156 while ( --maxLoop > 0 && !m_instancesTools.empty() ) {
157 IAlgTool* pTool = m_instancesTools.back();
159 m_instancesTools.pop_back();
160 unsigned long count = pTool->
refCount( );
163 if ( count <= startMinRefCount ) {
164 ON_DEBUG debug() <<
" Performing finalization of " << toolName
165 <<
" (refCount " << count <<
")" <<
endmsg;
168 if (!finalizeTool(pTool).isSuccess()) {
169 warning() <<
" FAILURE finalizing " << toolName <<
endmsg;
173 finalizedTools.push_back(pTool);
177 ON_DEBUG debug() <<
" Delaying finalization of " << toolName
178 <<
" (refCount " << count <<
")" <<
endmsg;
179 m_instancesTools.insert(
std::begin(m_instancesTools), pTool );
182 toolCount = m_instancesTools.size();
183 endRefCount = totalToolRefCount();
184 endMinRefCount = minimumToolRefCount();
199 ON_DEBUG debug() <<
"Deleting " << finalizedTools.size() <<
" finalized tools" <<
endmsg;
200 auto maxLoop = totalRefCount( finalizedTools ) + 1;
201 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
202 IAlgTool* pTool = finalizedTools.front();
203 finalizedTools.pop_front();
209 <<
" (refCount " << count <<
")" <<
endmsg;
211 finalizedTools.push_back(pTool);
218 if ( !m_instancesTools.empty() ) {
219 error() <<
"Unable to finalize and delete the following tools : ";
220 for (
const auto& iTool : m_instancesTools ) {
221 error() << iTool->name() <<
": " << iTool->refCount( ) <<
" ";
227 if ( !finalizedTools.empty() ) {
228 error() <<
"Failed to delete the following " << finalizedTools.size()
229 <<
" finalized tools. Bug in ToolSvc::finalize()?: ";
230 for (
const auto& iTool : finalizedTools ) {
231 error() << iTool->name() <<
": " << iTool->refCount( ) <<
" ";
236 if ( m_pHistorySvc ) m_pHistorySvc->release();
264 if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
266 return retrieve ( ba::erase_tail_copy(tooltype, s_PUBLIC.
size()),
267 iid , tool ,
this , createIf ) ;
271 if ( tooltype.
empty() ) {
272 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
275 auto pos = tooltype.
find(
'/');
276 if ( std::string::npos == pos ) {
277 return retrieve ( tooltype , tooltype , iid , tool , parent , createIf );
279 return retrieve ( tooltype.
substr( 0 , pos ),
280 tooltype.
substr( pos + 1 ),
281 iid , tool , parent , createIf ) ;
297 if( toolname.
empty() || (std::string::npos != tooltype.
find(
'/')) )
298 {
return retrieve ( tooltype , iid , tool , parent , createIf ) ; }
301 if ( ba::ends_with( toolname, s_PUBLIC ) )
304 return retrieve ( tooltype , ba::erase_tail_copy(toolname, s_PUBLIC.
size() ),
305 iid , tool ,
this , createIf ) ;
316 if( !parent ) parent =
this;
317 const std::string fullname = nameTool( toolname, parent );
323 return i->
name() == fullname && i->
parent() == parent;
325 if (it!=
std::end(m_instancesTools)) {
326 ON_DEBUG debug() <<
"Retrieved tool " << toolname <<
" with parent " << parent <<
endmsg;
334 warning() <<
"Tool " << toolname
335 <<
" not found and creation not requested" <<
endmsg;
338 sc = create( tooltype, toolname, parent, itool );
345 error() <<
"Tool " << toolname
346 <<
" either does not implement the correct interface, or its version is incompatible" 366 for(
const auto& tool: m_instancesTools) {
367 if (tool->type() == toolType) tools.
push_back( tool->name() );
396 if ( m_instancesTools.rend() !=
std::find( m_instancesTools.rbegin(),
397 m_instancesTools.rend(),
399 unsigned long count = tool->
refCount();
406 debug() <<
" Performing finalization of " << tool->
name()
407 <<
" (refCount " << count <<
")" <<
endmsg;
409 debug() <<
" Performing deletion of " << tool->
name() <<
endmsg;
411 debug() <<
"Performing finalization and deletion of " << tool->
name() <<
endmsg;
413 sc = finalizeTool(tool);
415 remove(m_instancesTools,tool);
429 return create( tooltype, toolname, parent, tool);
435 template <
typename T>
436 class ToolCreateGuard {
443 explicit ToolCreateGuard(T& tools): m_tools(tools) {}
447 ToolCreateGuard(ToolCreateGuard&&) noexcept =
default;
451 if (m_tool)
remove(m_tools,m_tool.
get());
452 m_tool.
reset(AlgTool::Factory::create(tooltype, tooltype, fullname, parent)) ;
454 if (m_tool) m_tools.push_back(m_tool.
get());
470 if (m_tool)
remove(m_tools,m_tool.
get());
474 template <
typename C>
475 ToolCreateGuard<C> make_toolCreateGuard(C&
c) {
476 return ToolCreateGuard<C>{ c };
498 error() <<
"create(): No Tool Type given" <<
endmsg;
503 if ( !parent ) parent =
this;
508 auto toolguard = make_toolCreateGuard(m_instancesTools);
512 if(
UNLIKELY(existsTool(fullname)) ) {
518 error() <<
"Tool " << fullname <<
" already exists with the same parent" <<
endmsg;
520 error() <<
"... In addition, the parent is the ToolSvc: public tools cannot be cloned!" <<
endmsg;
529 toolguard.create( tooltype, fullname, parent );
531 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
537 fatal() <<
"Exception with tag=" << Exception.
tag()
538 <<
" is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
541 fatal() << Exception <<
endmsg;
546 fatal() <<
"Standard std::exception is caught whilst instantiating tool '" 547 << tooltype <<
"'" <<
endmsg;
555 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '" 556 << tooltype <<
"'" <<
endmsg;
568 error() <<
"Error setting properties for tool '" 569 << fullname <<
"'" <<
endmsg;
577 sc = toolguard->sysInitialize();
583 <<
"GaudiException with tag=" << Exception.
tag()
584 <<
" caught whilst initializing tool '" << fullname <<
"'" << endmsg
591 <<
"Standard std::exception caught whilst initializing tool '" 592 << fullname <<
"'" << endmsg << Exception.
what() <<
endmsg;
598 <<
"UNKNOWN Exception caught whilst initializing tool '" 599 << fullname <<
"'" <<
endmsg;
605 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
611 sc = toolguard->sysStart();
614 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
632 if (m_pHistorySvc || service(
"HistorySvc",m_pHistorySvc,
false).isSuccess() ) {
633 m_pHistorySvc->registerAlgTool(*tool).ignore();
645 if ( !parent ) {
return this->
name() +
"." +
toolname; }
651 auto fullname = named_parent->name() +
"." +
toolname ;
655 error() <<
"Private Tools only allowed for components implementing INamedInterface" 667 [&](
const IAlgTool* tool) {
return tool->
name() == fullname; } );
668 return i !=
std::end(m_instancesTools);
682 sc = itool->sysFinalize();
688 <<
"GaudiException with tag=" << Exception.
tag()
689 <<
" caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg 696 <<
"Standard std::exception caught whilst finalizing tool '" 703 <<
"UNKNOWN Exception caught whilst finalizing tool '" 704 << toolName <<
"'" <<
endmsg;
716 return totalRefCount( m_instancesTools );
726 return i!=
std::end(m_instancesTools) ? (*i)->refCount() : 0;
738 auto i =
std::find(m_observers.begin(),m_observers.end(),obs);
739 if (i!=m_observers.end()) m_observers.erase(i);
741 m_observers.push_back(obs);
753 for (
auto& iTool : m_instancesTools ) {
756 if (
UNLIKELY(!iTool->sysStart().isSuccess())) {
758 error() << iTool->name() <<
" failed to start()" <<
endmsg;
764 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
779 for (
auto& iTool : m_instancesTools ) {
782 if (
UNLIKELY(!iTool->sysStop().isSuccess())) {
784 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
790 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.