20 #include <boost/algorithm/string/erase.hpp>
21 #include <boost/algorithm/string/predicate.hpp>
22 #include <boost/circular_buffer.hpp>
30 namespace ba = boost::algorithm;
32 #define ON_DEBUG if ( msgLevel( MSG::DEBUG ) )
33 #define ON_VERBOSE if ( msgLevel( MSG::VERBOSE ) )
51 using extends::extends;
66 bool createIf )
override;
70 const IInterface* parent,
bool createIf )
override;
73 std::vector<std::string>
getInstances( std::string_view toolType )
override;
79 std::vector<IAlgTool*>
getTools()
const override;
91 bool existsTool( std::string_view fullname )
const;
103 this,
"CheckedNamedToolsConfigured",
false,
104 "Check that tools which do not have the default name have some explicit configuration." };
111 #ifdef __cpp_lib_generic_unordered_lookup
113 using is_transparent = void;
114 std::size_t operator()(
IAlgTool const*
s )
const noexcept {
return std::hash<std::string_view>{}(
s->name() ); }
115 std::size_t operator()( std::string_view
s )
const noexcept {
return std::hash<std::string_view>{}(
s ); }
118 using is_transparent = void;
120 bool operator()(
IAlgTool const* lhs, std::string_view rhs )
const {
return lhs->
name() == rhs; }
121 bool operator()( std::string_view lhs,
IAlgTool const* rhs )
const {
return lhs == rhs->
name(); }
123 std::unordered_multiset<IAlgTool*, Hash, Equal>
m_map;
125 std::unordered_multimap<std::string_view, IAlgTool*>
m_map;
132 #ifdef __cpp_lib_generic_unordered_lookup
133 auto itm = std::find_if(
range.first,
range.second, [&](
auto const& p ) { return p == tool; } );
135 auto itm = std::find_if(
range.first,
range.second, [&](
auto const& p ) { return p.second == tool; } );
137 if ( itm !=
range.second )
m_map.erase( itm );
141 #ifdef __cpp_lib_generic_unordered_lookup
158 #ifdef __cpp_lib_generic_unordered_lookup
159 auto it = std::find_if(
range.first,
range.second, [&](
auto const& p ) { return p->parent() == parent; } );
160 return it !=
range.second ? *it :
nullptr;
163 std::find_if(
range.first,
range.second, [&](
auto const& p ) { return p.second->parent() == parent; } );
164 return it !=
range.second ? it->second :
nullptr;
167 std::vector<IAlgTool*>
grab() && {
184 template <
typename C>
185 unsigned long totalRefCount(
const C& toolList ) {
187 [&](
unsigned long count,
const IAlgTool*
tool ) {
return count +
tool->refCount(); } );
191 template <
typename C>
192 unsigned long minimumRefCount(
const C& toolList ) {
194 [](
unsigned long c,
const IAlgTool*
tool ) {
return std::min(
c,
tool->refCount() ); } );
232 info() <<
"Removing all tools created by ToolSvc" <<
endmsg;
238 log <<
" Tool List : ";
239 for (
const auto& iTool :
tools ) {
log << iTool->name() <<
":" << iTool->refCount() <<
" "; }
258 boost::circular_buffer<IAlgTool*> finalizedTools(
tools.size() );
260 size_t toolCount =
tools.size();
261 unsigned long startRefCount = 0;
262 unsigned long endRefCount = totalRefCount(
tools );
263 unsigned long startMinRefCount = 0;
264 unsigned long endMinRefCount = minimumRefCount(
tools );
265 while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
266 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
267 debug() << toolCount <<
" tools left to finalize. Summed refCounts: " << endRefCount <<
endmsg;
268 debug() <<
"Will finalize tools with refCount <= " << endMinRefCount <<
endmsg;
270 startMinRefCount = endMinRefCount;
271 startRefCount = endRefCount;
272 unsigned long maxLoop = toolCount + 1;
273 while ( --maxLoop > 0 && !
tools.empty() ) {
277 unsigned long count = pTool->
refCount();
279 const std::string& toolName = pTool->
name();
280 if ( count <= startMinRefCount ) {
281 ON_DEBUG debug() <<
" Performing finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
285 warning() <<
" FAILURE finalizing " << toolName <<
endmsg;
289 finalizedTools.push_back( pTool );
293 ON_DEBUG debug() <<
" Delaying finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
297 toolCount =
tools.size();
298 endRefCount = totalRefCount(
tools );
299 endMinRefCount = minimumRefCount(
tools );
314 ON_DEBUG debug() <<
"Deleting " << finalizedTools.size() <<
" finalized tools" <<
endmsg;
315 auto maxLoop = totalRefCount( finalizedTools ) + 1;
316 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
317 IAlgTool* pTool = finalizedTools.front();
318 finalizedTools.pop_front();
325 finalizedTools.push_back( pTool );
332 if ( !
tools.empty() ) {
333 error() <<
"Unable to finalize and delete the following tools : ";
334 for (
const auto& iTool :
tools ) { error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
339 if ( !finalizedTools.empty() ) {
340 error() <<
"Failed to delete the following " << finalizedTools.size()
341 <<
" finalized tools. Bug in ToolSvc::finalize()?: ";
342 for (
const auto& iTool : finalizedTools ) { error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
351 static const std::string s_PUBLIC =
":PUBLIC";
357 if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
359 tooltype.remove_suffix( s_PUBLIC.size() );
364 if ( tooltype.empty() ) {
365 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
368 auto pos = tooltype.find(
'/' );
369 if ( std::string_view::npos == pos ) {
return retrieve( tooltype, tooltype, iid,
tool, parent, createIf ); }
370 return retrieve( tooltype.substr( 0, pos ), tooltype.substr( pos + 1 ), iid,
tool, parent, createIf );
377 if (
toolname.empty() || ( std::string_view::npos != tooltype.find(
'/' ) ) ) {
378 return retrieve( tooltype, iid,
tool, parent, createIf );
382 if ( ba::ends_with(
toolname, s_PUBLIC ) ) {
384 toolname.remove_suffix( s_PUBLIC.size() );
393 if ( !parent ) parent =
this;
398 auto lock = std::scoped_lock{
m_mut };
400 if ( itool ) {
ON_DEBUG debug() <<
"Retrieved tool " <<
toolname <<
" with parent " << parent <<
endmsg; }
406 warning() <<
"Tool " <<
toolname <<
" not found and creation not requested" <<
endmsg;
409 sc =
create( std::string{ tooltype }, std::string{
toolname }, parent, itool );
416 error() <<
"Tool " <<
toolname <<
" either does not implement the correct interface, or its version is incompatible"
431 std::vector<std::string>
tools;
432 auto lock = std::scoped_lock{
m_mut };
434 if (
tool->type() == toolType )
tools.push_back(
tool->name() );
440 auto lock = std::scoped_lock{
m_mut };
443 [](
const IAlgTool*
t ) {
return t->name(); } );
448 auto lock = std::scoped_lock{
m_mut };
453 auto lock = std::scoped_lock{
m_mut };
457 unsigned long count =
tool->refCount();
464 debug() <<
" Performing finalization of " <<
tool->name() <<
" (refCount " << count <<
")" <<
endmsg;
466 debug() <<
" Performing deletion of " <<
tool->name() <<
endmsg;
468 debug() <<
"Performing finalization and deletion of " <<
tool->name() <<
endmsg;
480 const std::string&
toolname = tooltype;
487 template <
typename T>
488 class ToolCreateGuard {
492 std::unique_ptr<IAlgTool> m_tool;
495 explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
499 ToolCreateGuard( ToolCreateGuard&& ) noexcept =
default;
501 void create( const
std::
string& tooltype, const
std::
string& fullname, const
IInterface* parent ) {
503 if ( m_tool ) { m_tools.remove( m_tool.get() ); };
504 m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
506 if ( m_tool ) { m_tools.push_back( m_tool.get() ); }
518 if ( m_tool ) m_tools.remove( m_tool.get() );
522 template <
typename C>
523 ToolCreateGuard<C> make_toolCreateGuard( C&
c ) {
524 return ToolCreateGuard<C>{
c };
539 if ( tooltype.empty() ) {
540 error() <<
"create(): No Tool Type given" <<
endmsg;
545 if ( !parent ) parent =
this;
550 auto lock = std::scoped_lock{
m_mut };
558 if ( iAlgTool->name() ==
toolname && iAlgTool->parent() == parent ) {
561 error() <<
"Tool " << fullname <<
" already exists with the same parent" <<
endmsg;
562 if ( parent ==
this )
563 error() <<
"... In addition, the parent is the ToolSvc: public tools cannot be cloned!" <<
endmsg;
572 toolguard.create( tooltype, fullname, parent );
573 if ( !toolguard.get() ) {
574 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
579 fatal() <<
"Exception with tag=" << Exception.tag() <<
" is caught whilst instantiating tool '" << tooltype <<
"'"
583 fatal() << Exception <<
endmsg;
585 }
catch (
const std::exception& Exception ) {
587 fatal() <<
"Standard std::exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
590 fatal() << Exception.what() <<
endmsg;
594 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
608 sc = toolguard->sysInitialize();
612 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst initializing tool '" << fullname <<
"'"
615 }
catch (
const std::exception& Exception ) {
616 error() <<
"Standard std::exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg
617 << Exception.what() <<
endmsg;
620 error() <<
"UNKNOWN Exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg;
626 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
633 bool propsSet =
false;
637 bool isSet = joSvc.
isSet( mytool->
name() +
"." + prop->name() );
638 if ( isSet ) propsSet =
true;
641 warning() << tooltype <<
"/" << fullname
642 <<
" : Explicitly named tools should be configured! (assigned name=" <<
toolname <<
", default is "
643 << tooltype <<
")" <<
endmsg;
650 sc = toolguard->sysStart();
653 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
660 tool = toolguard.release();
675 if ( !parent ) {
return std::string{ this->
name() }.append(
"." ).append( toolname ); }
679 if ( named_parent ) {
680 auto fullname = std::string{ named_parent->name() }.append(
"." ).append(
toolname );
684 error() <<
"Private Tools only allowed for components implementing INamedInterface" <<
endmsg;
686 return std::string{
"." }.append(
toolname );
690 auto lock = std::scoped_lock{
m_mut };
697 const auto& toolName = itool->
name();
706 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst finalizing tool '" << toolName <<
"'"
709 }
catch (
const std::exception& Exception ) {
710 error() <<
"Standard std::exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg
711 << Exception.what() <<
endmsg;
714 error() <<
"UNKNOWN Exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg;
724 auto lock = std::scoped_lock{
m_mut };
726 auto lock = std::scoped_lock{
m_mut };
738 info() <<
"Listing Data Dependencies of all Tools";
742 std::ostringstream ost;
743 for (
auto& dh : idh->
inputHandles() ) { ost <<
"\n INPUT " << dh->fullKey(); }
744 for (
auto&
id : idh->
extraInputDeps() ) { ost <<
"\n EXTRA INPUT " <<
id; }
745 for (
auto& dh : idh->
outputHandles() ) { ost <<
"\n OUTPUT " << dh->fullKey(); }
747 if ( ost.str().length() > 0 ) { info() <<
"\n" << iTool->name() << ost.str(); }
749 error() <<
"can't cast " << iTool->name() <<
" to IDataHandleHolder!" <<
endmsg;
759 if ( !iTool->sysStart().isSuccess() ) {
761 error() << iTool->name() <<
" failed to start()" <<
endmsg;
766 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
780 if ( !iTool->sysStop().isSuccess() ) {
782 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
787 error() <<
"One or more AlgTools failed to stop()" <<
endmsg;