17 #include <boost/algorithm/string.hpp>
22 #include <tbb/concurrent_unordered_map.h>
23 #include <unordered_set>
31 #ifdef XAOD_STANDALONE
35 tbb::concurrent_unordered_map<std::string, std::function<std::unique_ptr<AsgComponent>(
const std::string&
name)>> s_factories;
36 tbb::concurrent_unordered_map<std::string,std::string> s_typeModuleMap;
38 struct ModuleData
final
40 std::atomic<bool> loaded{
false};
43 tbb::concurrent_unordered_map<std::string,ModuleData> s_modules;
48 StatusCode registerComponentFactory (
const std::string&
type,
const std::function<std::unique_ptr<AsgComponent>(
const std::string&
name)>& factory)
50 using namespace msgComponentConfig;
51 if (!s_factories.emplace (
type, factory).second)
53 ATH_MSG_ERROR (
"attempt to register a factory for type " <<
type <<
" that already has a factory");
54 return StatusCode::FAILURE;
56 return StatusCode::SUCCESS;
61 const std::function<std::unique_ptr<AsgComponent>(
const std::string&
name)> *getComponentFactory (
const std::string&
type)
63 using namespace msgComponentConfig;
64 if (
auto iter = s_factories.find (
type);
iter != s_factories.end())
66 static std::once_flag
flag;
67 std::call_once (
flag, [&] () {
68 const char *
path = gSystem->Getenv (
"LD_LIBRARY_PATH");
70 std::vector<std::string>
paths;
73 for (
const auto&
p :
paths)
75 if (
p.empty())
continue;
79 ANA_MSG_DEBUG (
"skipping non-existent directory for component factory maps: " <<
p);
84 for (
auto const&
entry : std::filesystem::directory_iterator(
p))
86 if (std::regex_search (
entry.path().filename().string(), pathRegex))
87 loadComponentFactoryMap (
entry.path());
91 if (
auto iter = s_typeModuleMap.find (
type);
iter != s_typeModuleMap.end())
94 loadComponentFactoryModule (
iter->second);
100 if (
auto iter = s_factories.find (
type);
iter != s_factories.end())
101 return &
iter->second;
104 ATH_MSG_WARNING (
"no component factory found for type " <<
type <<
" even after loading its module");
111 std::vector<std::string> getLoadedComponentFactoryTypes ()
113 using namespace msgComponentConfig;
115 std::vector<std::string>
result;
116 result.reserve (s_factories.size());
117 for (
const auto& pair : s_factories)
118 result.push_back (pair.first);
125 void loadComponentFactoryModule (
const std::string& moduleName,
const std::string& modulePath)
127 using namespace msgComponentConfig;
128 ATH_MSG_DEBUG (
"loading component factory module " << moduleName);
130 auto [
iter, inserted] = s_modules.emplace(std::piecewise_construct, std::forward_as_tuple(moduleName), std::forward_as_tuple());
131 if (
iter->second.loaded ==
true)
133 ATH_MSG_DEBUG (
"component factory module " << moduleName <<
" already loaded");
136 std::scoped_lock
lock(
iter->second.mutex);
137 if (
iter->second.loaded ==
true)
139 ATH_MSG_DEBUG (
"component factory module " << moduleName <<
" already loaded");
145 if (!modulePath.empty())
146 path = modulePath +
"/" + moduleName;
148 path = gSystem->DynamicPathName (moduleName.c_str());
150 if (gSystem->Load (
path.c_str()) < 0)
152 ATH_MSG_FATAL (
"failed to preload component factory module " << moduleName);
155 iter->second.loaded =
true;
160 void loadComponentFactoryMap (
const std::string&
path)
162 using namespace msgComponentConfig;
165 std::ifstream inputStream (
path);
171 std::unordered_set<std::string> foundModules;
172 std::unordered_set<std::string> skippedModules;
174 while (inputStream >> moduleName >>
typeName)
180 if (
auto iter = s_modules.find(moduleName);
iter != s_modules.end())
182 if (skippedModules.emplace(moduleName).second)
183 ANA_MSG_DEBUG (
"skipping information on " << moduleName <<
" from " <<
path <<
" because it has already been described in another file");
186 foundModules.insert(moduleName);
188 auto [
iter, success] = s_typeModuleMap.emplace (
typeName, moduleName);
191 if (
iter->second != moduleName)
194 <<
": already registered from " <<
iter->second
195 <<
", but trying to register from " << moduleName);
199 ATH_MSG_DEBUG (
"component factory type " <<
typeName <<
" registered twice for module " << moduleName);
203 for (
const auto& moduleName : foundModules)
204 s_modules.emplace(std::piecewise_construct, std::forward_as_tuple(moduleName), std::forward_as_tuple());