Go to the documentation of this file.
20 #include "boost/algorithm/string/erase.hpp"
21 #include "boost/algorithm/string/predicate.hpp"
22 #include "boost/circular_buffer.hpp"
29 namespace ba = boost::algorithm;
31 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
32 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
37 unsigned long totalRefCount(
const C& toolList )
41 [&](
unsigned long count,
const IAlgTool*
tool ) {
return count +
tool->refCount(); } );
46 void remove( C&
c,
typename C::const_reference i ) {
90 info() <<
"Removing all tools created by ToolSvc" <<
endmsg;
95 log <<
" Tool List : ";
96 for (
const auto& iTool :
m_instancesTools ) {
log << iTool->name() <<
":" << iTool->refCount() <<
" "; }
118 unsigned long startRefCount = 0;
120 unsigned long startMinRefCount = 0;
122 while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
123 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
124 debug() << toolCount <<
" tools left to finalize. Summed refCounts: " << endRefCount <<
endmsg;
125 debug() <<
"Will finalize tools with refCount <= " << endMinRefCount <<
endmsg;
127 startMinRefCount = endMinRefCount;
128 startRefCount = endRefCount;
129 unsigned long maxLoop = toolCount + 1;
134 unsigned long count = pTool->
refCount();
137 if ( count <= startMinRefCount ) {
138 ON_DEBUG debug() <<
" Performing finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
142 warning() <<
" FAILURE finalizing " << toolName <<
endmsg;
146 finalizedTools.push_back( pTool );
150 ON_DEBUG debug() <<
" Delaying finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
171 ON_DEBUG debug() <<
"Deleting " << finalizedTools.size() <<
" finalized tools" <<
endmsg;
172 auto maxLoop = totalRefCount( finalizedTools ) + 1;
173 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
174 IAlgTool* pTool = finalizedTools.front();
175 finalizedTools.pop_front();
182 finalizedTools.push_back( pTool );
190 error() <<
"Unable to finalize and delete the following tools : ";
191 for (
const auto& iTool :
m_instancesTools ) { error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
196 if ( !finalizedTools.empty() ) {
197 error() <<
"Failed to delete the following " << finalizedTools.size()
198 <<
" finalized tools. Bug in ToolSvc::finalize()?: ";
199 for (
const auto& iTool : finalizedTools ) { error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
224 if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
226 tooltype.remove_suffix( s_PUBLIC.size() );
231 if ( tooltype.empty() ) {
232 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
235 auto pos = tooltype.find(
'/' );
236 if ( std::string_view::npos == pos ) {
return retrieve( tooltype, tooltype, iid,
tool, parent, createIf ); }
237 return retrieve( tooltype.substr( 0, pos ), tooltype.substr( pos + 1 ), iid,
tool, parent, createIf );
249 if (
toolname.empty() || ( std::string_view::npos != tooltype.find(
'/' ) ) ) {
250 return retrieve( tooltype, iid,
tool, parent, createIf );
254 if ( ba::ends_with(
toolname, s_PUBLIC ) ) {
256 toolname.remove_suffix( s_PUBLIC.size() );
260 auto lock = std::scoped_lock{
m_mut };
268 if ( !parent ) parent =
this;
274 [&](
const IAlgTool* i ) {
return i->
name() == fullname && i->
parent() == parent; } );
284 warning() <<
"Tool " <<
toolname <<
" not found and creation not requested" <<
endmsg;
294 error() <<
"Tool " <<
toolname <<
" either does not implement the correct interface, or its version is incompatible"
311 auto lock = std::scoped_lock{
m_mut };
322 auto lock = std::scoped_lock{
m_mut };
325 [](
const IAlgTool*
t ) {
return t->name(); } );
332 auto lock = std::scoped_lock{
m_mut };
339 auto lock = std::scoped_lock{
m_mut };
343 unsigned long count =
tool->refCount();
350 debug() <<
" Performing finalization of " <<
tool->name() <<
" (refCount " << count <<
")" <<
endmsg;
352 debug() <<
" Performing deletion of " <<
tool->name() <<
endmsg;
354 debug() <<
"Performing finalization and deletion of " <<
tool->name() <<
endmsg;
376 template <
typename T>
377 class ToolCreateGuard {
384 explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
388 ToolCreateGuard( ToolCreateGuard&& ) noexcept =
default;
390 void create( const
std::
string& tooltype, const
std::
string& fullname, const
IInterface* parent ) {
392 if ( m_tool )
remove( m_tools, m_tool.
get() );
393 m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
395 if ( m_tool ) m_tools.push_back( m_tool.
get() );
407 if ( m_tool )
remove( m_tools, m_tool.
get() );
411 template <
typename C>
412 ToolCreateGuard<C> make_toolCreateGuard( C&
c ) {
413 return ToolCreateGuard<C>{
c };
430 auto lock = std::scoped_lock{
m_mut };
432 if ( tooltype.
empty() ) {
433 error() <<
"create(): No Tool Type given" <<
endmsg;
438 if ( !parent ) parent =
this;
453 error() <<
"Tool " << fullname <<
" already exists with the same parent" <<
endmsg;
454 if ( parent ==
this )
455 error() <<
"... In addition, the parent is the ToolSvc: public tools cannot be cloned!" <<
endmsg;
464 toolguard.create( tooltype, fullname, parent );
465 if ( !toolguard.get() ) {
466 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
471 fatal() <<
"Exception with tag=" << Exception.tag() <<
" is caught whilst instantiating tool '" << tooltype <<
"'"
475 fatal() << Exception <<
endmsg;
479 fatal() <<
"Standard std::exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
482 fatal() << Exception.what() <<
endmsg;
486 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
500 sc = toolguard->sysInitialize();
504 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst initializing tool '" << fullname <<
"'"
508 error() <<
"Standard std::exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg
509 << Exception.what() <<
endmsg;
512 error() <<
"UNKNOWN Exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg;
518 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
524 sc = toolguard->sysStart();
527 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
534 tool = toolguard.release();
557 if ( named_parent ) {
562 error() <<
"Private Tools only allowed for components implementing INamedInterface" <<
endmsg;
571 auto lock = std::scoped_lock{ m_mut };
574 return i !=
std::end( m_instancesTools );
583 const auto& toolName = itool->name();
588 sc = itool->sysFinalize();
592 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst finalizing tool '" << toolName <<
"'"
596 error() <<
"Standard std::exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg
597 << Exception.what() <<
endmsg;
600 error() <<
"UNKNOWN Exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg;
628 auto lock = std::scoped_lock{
m_mut };
630 auto lock = std::scoped_lock{
m_mut };
648 if ( !iTool->sysStart().isSuccess() ) {
650 error() << iTool->name() <<
" failed to start()" <<
endmsg;
655 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
672 if ( !iTool->sysStop().isSuccess() ) {
674 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
679 error() <<
"One or more AlgTools failed to stop()" <<
endmsg;
virtual StatusCode registerAlgTool(const IAlgTool &)=0
Gaudi::StateMachine::State m_state
Service state
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.
StatusCode finalize() override
void bindPropertiesTo(Gaudi::Interfaces::IOptionsSvc &optsSvc)
const std::vector< IAlgTool * > & tools() const
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
const std::string & name() const override
Retrieve name of the service
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
const StatusCode & ignore() const
Allow discarding a StatusCode without warning.
constexpr static const auto SUCCESS
#define DECLARE_COMPONENT(type)
Gaudi::StateMachine::State m_targetState
Service state
constexpr static const auto FAILURE
virtual unsigned long refCount() const =0
Current reference count.
virtual unsigned long release()=0
Release Interface instance.
StatusCode service(const std::string &name, const T *&psvc, bool createIf=true) const
Access a service by name, creating it if it doesn't already exist.
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator