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 ) )
52 using extends::extends;
68 bool createIf )
override;
72 const IInterface* parent,
bool createIf )
override;
75 std::vector<std::string>
getInstances( std::string_view toolType )
override;
81 std::vector<IAlgTool*>
getTools()
const override;
93 bool existsTool( std::string_view fullname )
const;
106 this,
"CheckedNamedToolsConfigured",
false,
107 "Check that tools which do not have the default name have some explicit configuration." };
114 #ifdef __cpp_lib_generic_unordered_lookup
116 using is_transparent = void;
117 std::size_t operator()(
IAlgTool const*
s )
const noexcept {
return std::hash<std::string_view>{}(
s->name() ); }
118 std::size_t operator()( std::string_view
s )
const noexcept {
return std::hash<std::string_view>{}(
s ); }
121 using is_transparent = void;
123 bool operator()(
IAlgTool const* lhs, std::string_view rhs )
const {
return lhs->
name() == rhs; }
124 bool operator()( std::string_view lhs,
IAlgTool const* rhs )
const {
return lhs == rhs->
name(); }
126 std::unordered_multiset<IAlgTool*, Hash, Equal>
m_map;
128 std::unordered_multimap<std::string_view, IAlgTool*>
m_map;
135 #ifdef __cpp_lib_generic_unordered_lookup
136 auto itm = std::find_if(
range.first,
range.second, [&](
auto const& p ) { return p == tool; } );
138 auto itm = std::find_if(
range.first,
range.second, [&](
auto const& p ) { return p.second == tool; } );
140 if ( itm !=
range.second )
m_map.erase( itm );
144 #ifdef __cpp_lib_generic_unordered_lookup
161 #ifdef __cpp_lib_generic_unordered_lookup
162 auto it = std::find_if(
range.first,
range.second, [&](
auto const& p ) { return p->parent() == parent; } );
163 return it !=
range.second ? *it :
nullptr;
166 std::find_if(
range.first,
range.second, [&](
auto const& p ) { return p.second->parent() == parent; } );
167 return it !=
range.second ? it->second :
nullptr;
170 std::vector<IAlgTool*>
grab() && {
187 template <
typename C>
188 unsigned long totalRefCount(
const C& toolList ) {
190 [&](
unsigned long count,
const IAlgTool*
tool ) {
return count +
tool->refCount(); } );
194 template <
typename C>
195 unsigned long minimumRefCount(
const C& toolList ) {
197 [](
unsigned long c,
const IAlgTool*
tool ) {
return std::min(
c,
tool->refCount() ); } );
241 info() <<
"Removing all tools created by ToolSvc" <<
endmsg;
247 log <<
" Tool List : ";
248 for (
const auto& iTool :
tools ) {
log << iTool->name() <<
":" << iTool->refCount() <<
" "; }
267 boost::circular_buffer<IAlgTool*> finalizedTools(
tools.size() );
269 size_t toolCount =
tools.size();
270 unsigned long startRefCount = 0;
271 unsigned long endRefCount = totalRefCount(
tools );
272 unsigned long startMinRefCount = 0;
273 unsigned long endMinRefCount = minimumRefCount(
tools );
274 while ( toolCount > 0 && endRefCount > 0 && ( endRefCount != startRefCount || endMinRefCount != startMinRefCount ) ) {
275 ON_DEBUG if ( endMinRefCount != startMinRefCount ) {
276 debug() << toolCount <<
" tools left to finalize. Summed refCounts: " << endRefCount <<
endmsg;
277 debug() <<
"Will finalize tools with refCount <= " << endMinRefCount <<
endmsg;
279 startMinRefCount = endMinRefCount;
280 startRefCount = endRefCount;
281 unsigned long maxLoop = toolCount + 1;
282 while ( --maxLoop > 0 && !
tools.empty() ) {
286 unsigned long count = pTool->
refCount();
288 const std::string& toolName = pTool->
name();
289 if ( count <= startMinRefCount ) {
290 ON_DEBUG debug() <<
" Performing finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
294 warning() <<
" FAILURE finalizing " << toolName <<
endmsg;
298 finalizedTools.push_back( pTool );
302 ON_DEBUG debug() <<
" Delaying finalization of " << toolName <<
" (refCount " << count <<
")" <<
endmsg;
306 toolCount =
tools.size();
307 endRefCount = totalRefCount(
tools );
308 endMinRefCount = minimumRefCount(
tools );
323 ON_DEBUG debug() <<
"Deleting " << finalizedTools.size() <<
" finalized tools" <<
endmsg;
324 auto maxLoop = totalRefCount( finalizedTools ) + 1;
325 while ( --maxLoop > 0 && !finalizedTools.empty() ) {
326 IAlgTool* pTool = finalizedTools.front();
327 finalizedTools.pop_front();
334 finalizedTools.push_back( pTool );
341 if ( !
tools.empty() ) {
342 error() <<
"Unable to finalize and delete the following tools : ";
343 for (
const auto& iTool :
tools ) { error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
348 if ( !finalizedTools.empty() ) {
349 error() <<
"Failed to delete the following " << finalizedTools.size()
350 <<
" finalized tools. Bug in ToolSvc::finalize()?: ";
351 for (
const auto& iTool : finalizedTools ) { error() << iTool->name() <<
": " << iTool->refCount() <<
" "; }
365 static const std::string s_PUBLIC =
":PUBLIC";
374 if ( ba::ends_with( tooltype, s_PUBLIC ) ) {
376 tooltype.remove_suffix( s_PUBLIC.size() );
381 if ( tooltype.empty() ) {
382 error() <<
"retrieve(): No Tool Type/Name given" <<
endmsg;
385 auto pos = tooltype.find(
'/' );
386 if ( std::string_view::npos == pos ) {
return retrieve( tooltype, tooltype, iid,
tool, parent, createIf ); }
387 return retrieve( tooltype.substr( 0, pos ), tooltype.substr( pos + 1 ), iid,
tool, parent, createIf );
399 if (
toolname.empty() || ( std::string_view::npos != tooltype.find(
'/' ) ) ) {
400 return retrieve( tooltype, iid,
tool, parent, createIf );
404 if ( ba::ends_with(
toolname, s_PUBLIC ) ) {
406 toolname.remove_suffix( s_PUBLIC.size() );
415 if ( !parent ) parent =
this;
420 auto lock = std::scoped_lock{
m_mut };
422 if ( itool ) {
ON_DEBUG debug() <<
"Retrieved tool " <<
toolname <<
" with parent " << parent <<
endmsg; }
428 warning() <<
"Tool " <<
toolname <<
" not found and creation not requested" <<
endmsg;
431 sc =
create( std::string{ tooltype }, std::string{
toolname }, parent, itool );
438 error() <<
"Tool " <<
toolname <<
" either does not implement the correct interface, or its version is incompatible"
455 std::vector<std::string>
tools;
456 auto lock = std::scoped_lock{
m_mut };
458 if (
tool->type() == toolType )
tools.push_back(
tool->name() );
466 auto lock = std::scoped_lock{
m_mut };
469 [](
const IAlgTool*
t ) {
return t->name(); } );
476 auto lock = std::scoped_lock{
m_mut };
483 auto lock = std::scoped_lock{
m_mut };
487 unsigned long count =
tool->refCount();
494 debug() <<
" Performing finalization of " <<
tool->name() <<
" (refCount " << count <<
")" <<
endmsg;
496 debug() <<
" Performing deletion of " <<
tool->name() <<
endmsg;
498 debug() <<
"Performing finalization and deletion of " <<
tool->name() <<
endmsg;
513 const std::string&
toolname = tooltype;
520 template <
typename T>
521 class ToolCreateGuard {
525 std::unique_ptr<IAlgTool> m_tool;
528 explicit ToolCreateGuard( T& tools ) : m_tools( tools ) {}
532 ToolCreateGuard( ToolCreateGuard&& ) noexcept =
default;
534 void create( const
std::
string& tooltype, const
std::
string& fullname, const
IInterface* parent ) {
536 if ( m_tool ) { m_tools.remove( m_tool.get() ); };
537 m_tool = AlgTool::Factory::create( tooltype, tooltype, fullname, parent );
539 if ( m_tool ) { m_tools.push_back( m_tool.get() ); }
551 if ( m_tool ) m_tools.remove( m_tool.get() );
555 template <
typename C>
556 ToolCreateGuard<C> make_toolCreateGuard( C&
c ) {
557 return ToolCreateGuard<C>{
c };
575 if ( tooltype.empty() ) {
576 error() <<
"create(): No Tool Type given" <<
endmsg;
581 if ( !parent ) parent =
this;
586 auto lock = std::scoped_lock{
m_mut };
594 if ( iAlgTool->name() ==
toolname && iAlgTool->parent() == parent ) {
597 error() <<
"Tool " << fullname <<
" already exists with the same parent" <<
endmsg;
598 if ( parent ==
this )
599 error() <<
"... In addition, the parent is the ToolSvc: public tools cannot be cloned!" <<
endmsg;
608 toolguard.create( tooltype, fullname, parent );
609 if ( !toolguard.get() ) {
610 error() <<
"Cannot create tool " << tooltype <<
" (No factory found)" <<
endmsg;
615 fatal() <<
"Exception with tag=" << Exception.tag() <<
" is caught whilst instantiating tool '" << tooltype <<
"'"
619 fatal() << Exception <<
endmsg;
621 }
catch (
const std::exception& Exception ) {
623 fatal() <<
"Standard std::exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
626 fatal() << Exception.what() <<
endmsg;
630 fatal() <<
"UNKNOWN Exception is caught whilst instantiating tool '" << tooltype <<
"'" <<
endmsg;
644 sc = toolguard->sysInitialize();
648 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst initializing tool '" << fullname <<
"'"
651 }
catch (
const std::exception& Exception ) {
652 error() <<
"Standard std::exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg
653 << Exception.what() <<
endmsg;
656 error() <<
"UNKNOWN Exception caught whilst initializing tool '" << fullname <<
"'" <<
endmsg;
662 error() <<
"Error initializing tool '" << fullname <<
"'" <<
endmsg;
669 bool propsSet =
false;
673 bool isSet = joSvc.
isSet( mytool->
name() +
"." + prop->name() );
674 if ( isSet ) propsSet =
true;
677 warning() << tooltype <<
"/" << fullname
678 <<
" : Explicitly named tools should be configured! (assigned name=" <<
toolname <<
", default is "
679 << tooltype <<
")" <<
endmsg;
686 sc = toolguard->sysStart();
689 error() <<
"Error starting tool '" << fullname <<
"'" <<
endmsg;
696 tool = toolguard.release();
714 if ( !parent ) {
return std::string{ this->
name() }.append(
"." ).append( toolname ); }
718 if ( named_parent ) {
719 auto fullname = std::string{ named_parent->name() }.append(
"." ).append(
toolname );
723 error() <<
"Private Tools only allowed for components implementing INamedInterface" <<
endmsg;
725 return std::string{
"." }.append(
toolname );
732 auto lock = std::scoped_lock{ m_mut };
733 return m_instancesTools.contains( fullname );
742 const auto& toolName = itool->
name();
751 error() <<
"GaudiException with tag=" << Exception.tag() <<
" caught whilst finalizing tool '" << toolName <<
"'"
754 }
catch (
const std::exception& Exception ) {
755 error() <<
"Standard std::exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg
756 << Exception.what() <<
endmsg;
759 error() <<
"UNKNOWN Exception caught whilst finalizing tool '" << toolName <<
"'" <<
endmsg;
771 auto lock = std::scoped_lock{
m_mut };
773 auto lock = std::scoped_lock{
m_mut };
788 info() <<
"Listing Data Dependencies of all Tools";
792 std::ostringstream ost;
793 for (
auto& dh : idh->
inputHandles() ) { ost <<
"\n INPUT " << dh->fullKey(); }
794 for (
auto&
id : idh->
extraInputDeps() ) { ost <<
"\n EXTRA INPUT " <<
id; }
795 for (
auto& dh : idh->
outputHandles() ) { ost <<
"\n OUTPUT " << dh->fullKey(); }
797 if ( ost.str().length() > 0 ) { info() <<
"\n" << iTool->name() << ost.str(); }
799 error() <<
"can't cast " << iTool->name() <<
" to IDataHandleHolder!" <<
endmsg;
809 if ( !iTool->sysStart().isSuccess() ) {
811 error() << iTool->name() <<
" failed to start()" <<
endmsg;
816 error() <<
"One or more AlgTools failed to start()" <<
endmsg;
833 if ( !iTool->sysStop().isSuccess() ) {
835 error() << iTool->name() <<
" failed to stop()" <<
endmsg;
840 error() <<
"One or more AlgTools failed to stop()" <<
endmsg;