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 ) {
69 error() <<
"Unable to initialize the Service" <<
endmsg;
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 ) {
log << iTool->name() <<
":" << iTool->refCount() <<
" "; }
138 unsigned long startRefCount = 0;
140 unsigned long startMinRefCount = 0;
142 while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
143 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
144 debug() << toolCount <<
" tools left to finalize. Summed refCounts: " << endRefCount <<
endmsg;
145 debug() <<
"Will finalize tools with refCount <= " << endMinRefCount <<
endmsg;
147 startMinRefCount = endMinRefCount;
148 startRefCount = endRefCount;
149 unsigned long maxLoop = toolCount + 1;
154 unsigned long count = pTool->
refCount();
157 if ( count <= startMinRefCount ) {
158 ON_DEBUG debug() <<
" Performing finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
166 finalizedTools.push_back( pTool );
170 ON_DEBUG debug() <<
" Delaying finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
192 auto maxLoop = totalRefCount( finalizedTools ) + 1;
193 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
194 IAlgTool* pTool = finalizedTools.front();
195 finalizedTools.pop_front();
202 finalizedTools.push_back( pTool );
210 error() <<
"Unable to finalize and delete the following tools : ";
211 for (
const auto& iTool :
m_instancesTools ) {
error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
216 if ( !finalizedTools.empty() ) {
217 error() <<
"Failed to delete the following " << finalizedTools.size()
218 <<
" finalized tools. Bug in ToolSvc::finalize()?: ";
219 for (
const auto& iTool : finalizedTools ) {
error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
244 if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
246 return retrieve( ba::erase_tail_copy( tooltype, s_PUBLIC.
size() ), iid, tool,
this, createIf );
250 if ( tooltype.
empty() ) {
251 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
254 auto pos = tooltype.
find(
'/' );
255 if ( std::string::npos == pos ) {
return retrieve( tooltype, tooltype, iid, tool, parent, createIf ); }
256 return retrieve( tooltype.
substr( 0, pos ), tooltype.
substr( pos + 1 ), iid, tool, parent, createIf );
268 if (
toolname.empty() || ( std::string::npos != tooltype.
find(
'/' ) ) ) {
269 return retrieve( tooltype, iid, tool, parent, createIf );
273 if ( ba::ends_with(
toolname, s_PUBLIC ) ) {
275 return retrieve( tooltype, ba::erase_tail_copy(
toolname, s_PUBLIC.size() ), iid, tool,
this, createIf );
286 if ( !parent ) parent =
this;
292 [&](
const IAlgTool* i ) {
return i->
name() == fullname && i->
parent() == parent; } );
312 error() <<
"Tool " <<
toolname <<
" either does not implement the correct interface, or its version is incompatible" 332 if ( tool->type() == toolType ) tools.
push_back( tool->name() );
361 unsigned long count = tool->
refCount();
368 debug() <<
" Performing finalization of " << tool->
name() <<
" (refCount " << count <<
")" <<
endmsg;
372 debug() <<
"Performing finalization and deletion of " << tool->
name() <<
endmsg;
394 template <
typename T>
395 class ToolCreateGuard {
402 explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
406 ToolCreateGuard( ToolCreateGuard&& ) noexcept =
default;
408 void create( const
std::
string& tooltype, const
std::
string& fullname, const
IInterface* parent ) {
410 if ( m_tool )
remove( m_tools, m_tool.
get() );
411 m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
413 if ( m_tool ) m_tools.push_back( m_tool.get() );
425 if ( m_tool )
remove( m_tools, m_tool.get() );
429 template <
typename C>
430 ToolCreateGuard<C> make_toolCreateGuard( C&
c ) {
431 return ToolCreateGuard<C>{
c};
451 error() <<
"create(): No Tool Type given" <<
endmsg;
456 if ( !parent ) parent =
this;
471 error() <<
"Tool " << fullname <<
" already exists with the same parent" <<
endmsg;
472 if ( parent ==
this )
473 error() <<
"... In addition, the parent is the ToolSvc: public tools cannot be cloned!" <<
endmsg;
482 toolguard.create( tooltype, fullname, parent );
483 if (
UNLIKELY( !toolguard.get() ) ) {
484 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
489 fatal() <<
"Exception with tag=" << Exception.
tag() <<
" is caught whilst instantiating tool '" << tooltype <<
"'" 497 fatal() <<
"Standard std::exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
504 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
512 AlgTool* mytool = dynamic_cast<AlgTool*>( toolguard.get() );
516 error() <<
"Error setting properties for tool '" << fullname <<
"'" <<
endmsg;
524 sc = toolguard->sysInitialize();
528 error() <<
"GaudiException with tag=" << Exception.
tag() <<
" caught whilst initializing tool '" << fullname <<
"'" 532 error() <<
"Standard std::exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg 536 error() <<
"UNKNOWN Exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg;
542 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
548 sc = toolguard->sysStart();
551 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
577 if ( !parent ) {
return this->
name() +
"." +
toolname; }
581 if ( named_parent ) {
582 auto fullname = named_parent->name() +
"." +
toolname;
586 error() <<
"Private Tools only allowed for components implementing INamedInterface" <<
endmsg;
597 [&](
const IAlgTool* tool ) {
return tool->
name() == fullname; } );
598 return i !=
std::end( m_instancesTools );
612 sc = itool->sysFinalize();
616 error() <<
"GaudiException with tag=" << Exception.
tag() <<
" caught whilst finalizing tool '" << toolName <<
"'" 620 error() <<
"Standard std::exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg 624 error() <<
"UNKNOWN Exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg;
672 if (
UNLIKELY( !iTool->sysStart().isSuccess() ) ) {
674 error() << iTool->name() <<
" failed to start()" <<
endmsg;
679 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
696 if (
UNLIKELY( !iTool->sysStop().isSuccess() ) ) {
698 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
703 error() <<
"One or more AlgTools failed to stop()" <<
endmsg;
Gaudi::StateMachine::State m_targetState
Service state.
StatusCode initialize() override
Define general base for Gaudi exception.
Gaudi::StateMachine::State m_state
Service state.
StatusCode finalize() override
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
virtual const std::string & tag() const
name tag for the exception, or exception type
constexpr static const auto SUCCESS
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
auto get(const Handle &handle, const Algo &, const EventContext &) -> decltype(details::deref(handle.get()))
virtual const std::string & name() const =0
Retrieve the name of the instance.
#define DECLARE_COMPONENT(type)
const std::string & name() const override
Retrieve name of the service.
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
This class is used for returning status codes from appropriate routines.
virtual StatusCode registerAlgTool(const IAlgTool &)=0
Definition of the basic interface.
virtual unsigned long refCount() const =0
Current reference count.
MsgStream & verbose() const
shortcut for the method msgStream(MSG::VERBOSE)
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
StatusCode setProperties()
Method for setting declared properties to the values specified for the job.
const StatusCode & ignore() const
Ignore/check StatusCode.
virtual unsigned long release()=0
Release Interface instance.
constexpr static const auto FAILURE
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.
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
virtual StatusCode queryInterface(const InterfaceID &ti, void **pp)=0
Set the void** to the pointer to the requested interface of the instance.