14 #include <Gaudi/PluginService.h>
27 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
28 #define REG_SCOPE_LOCK \
29 std::lock_guard<std::recursive_mutex> _guard(m_mutex);
32 std::mutex registrySingletonMutex;
34 #define SINGLETON_LOCK \
35 std::lock_guard<std::mutex> _guard(::registrySingletonMutex);
37 #define REG_SCOPE_LOCK
38 #define SINGLETON_LOCK
47 constexpr
struct is_space_t {
48 bool operator()(
int i)
const {
return std::isspace(i); }
52 static inline std::string <rim(std::string &
s) {
54 std::find_if_not(s.begin(), s.end(), is_space ) );
59 static inline std::string &rtrim(std::string &s) {
60 s.erase(std::find_if_not(s.rbegin(), s.rend(), is_space).base(),
65 static inline std::string &trim(std::string &s) {
66 return ltrim(rtrim(s));
74 inline void factoryInfoSetHelper(std::string&
dest,
const std::string
value,
75 const std::string& desc,
76 const std::string&
id) {
79 }
else if (dest != value) {
81 "new factory loaded for '" +
id +
"' with different "
82 + desc +
": " + dest +
" != " + value );
88 void operator() (
const char c) {
97 name.push_back(
'_');
break;
99 name.push_back(
'r');
break;
101 name.push_back(
'p');
break;
104 name.push_back(c);
break;
109 std::string old_style_name(
const std::string& name) {
110 return std::for_each(name.begin(), name.end(), OldStyleCnv()).name;
114 namespace Gaudi {
namespace PluginService {
119 return m_msg.c_str();
129 auto realname = std::unique_ptr<char,decltype(free)*>( abi::__cxa_demangle(
id.c_str(),
nullptr,
nullptr, &status),
131 if (!realname)
return id;
132 return std::string{realname.get()};
151 const char* envVar =
"PATH";
152 const char sep =
';';
154 const char* envVar =
"LD_LIBRARY_PATH";
155 const char sep =
':';
157 char *search_path = ::getenv(envVar);
159 logger().
debug(std::string(
"searching factories in ") + envVar);
160 std::string
path(search_path);
161 std::string::size_type pos = 0;
162 std::string::size_type newpos = 0;
163 while (pos != std::string::npos) {
166 newpos = path.find(sep, pos);
167 if (newpos != std::string::npos) {
168 dirName = path.substr(pos, newpos - pos);
171 dirName = path.substr(pos);
174 logger().
debug(std::string(
" looking into ") + dirName);
176 DIR *dir = opendir(dirName.c_str());
178 struct dirent * entry;
179 while ((entry = readdir(dir))) {
180 std::string
name(entry->d_name);
182 std::string::size_type extpos = name.find(
".components");
183 if ((extpos != std::string::npos) &&
184 ((extpos+11) == name.size())) {
185 std::string fullPath = (dirName +
'/' +
name);
188 stat(fullPath.c_str(), &buf);
189 if (!S_ISREG(buf.st_mode))
continue;
195 int factoriesCount = 0;
202 if (line.empty() || line[0] ==
'#')
continue;
204 auto pos = line.find(
':');
205 if (pos == std::string::npos) {
211 const std::string lib(line, 0, pos);
212 const std::string fact(line, pos+1);
214 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
216 std::string old_name = old_style_name(fact);
217 if (fact != old_name) {
239 const std::string&
type,
const std::string& rtype,
240 const std::string& className,
244 auto entry = facts.find(
id);
245 if (entry == facts.end())
248 entry = facts.emplace(
id,
FactoryInfo(
"unknown", factory,
249 type, rtype, className, props) ).first;
252 if (!entry->second.ptr) entry->second.ptr = factory;
253 factoryInfoSetHelper(entry->second.type, type,
"type",
id);
254 factoryInfoSetHelper(entry->second.rtype, rtype,
"return type",
id);
255 factoryInfoSetHelper(entry->second.className, className,
"class",
id);
257 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
259 std::string old_name = old_style_name(
id);
261 add(old_name, factory, type, rtype, className, props)
264 return entry->second;
270 auto f = facts.find(
id);
271 if (f != facts.end())
273 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES
274 const Properties& props = f->second.properties;
275 if (props.find(
"ReflexName") != props.end())
276 logger().
warning(
"requesting factory via old name '" +
id +
"'"
277 "use '" + f->second.className +
"' instead");
279 if (!f->second.ptr) {
280 if (!dlopen(f->second.library.c_str(), RTLD_LAZY | RTLD_GLOBAL)) {
282 " for factory " +
id);
283 char *dlmsg = dlerror();
289 if (f->second.type == type)
return f->second.ptr;
290 logger().
warning(
"found factory " +
id +
", but of wrong type: " +
300 auto f = facts.find(
id);
301 return (f != facts.end()) ? f->second : unknown;
306 const std::string& k,
307 const std::string& v) {
310 auto f = facts.find(
id);
311 if (f != facts.end()) f->second.properties[k] = v;
319 for (
const auto& f : facts )
321 if (f.second.ptr) l.insert(f.first);
327 static const char* levels[] = {
"DEBUG : ",
331 if (lvl >=
level()) {
332 std::cerr << levels[lvl] << msg << std::endl;
336 static std::unique_ptr<Logger> s_logger(
new Logger);
343 using namespace Details;
347 else if (debugLevel > 0)
353 using namespace Details;
string to_string(const T &value)
const FactoryInfo & getInfo(const std::string &id) const
Retrieve the FactoryInfo object for an id.
Registry & addProperty(const std::string &id, const std::string &k, const std::string &v)
Add a property to an already existing FactoryInfo object (via its id.)
Registry()
Private constructor for the singleton pattern.
void initialize()
Initialize the registry loading the list of factories from the .component files in the library search...
GAUDIPS_API Logger & logger()
Return the current logger instance.
GAUDIPS_API void * getCreator(const std::string &id, const std::string &type)
Function used to load a specific factory function.
std::set< KeyType > loadedFactories() const
Return a list of all the known and loaded factories.
std::map< KeyType, std::string > Properties
Type used for the properties implementation.
Simple logging class, just to provide a default implementation.
GAUDIPS_API int Debug()
Backward compatibility with Reflex.
void * get(const std::string &id, const std::string &type) const
Retrieve the factory for the given id.
const FactoryMap & factories() const
Return the known factories (loading the list if not yet done).
GAUDIPS_API std::string demangle(const std::type_info &id)
Return a canonical name for type_info object (implementation borrowed from GaudiKernel/System).
virtual void report(Level lvl, const std::string &msg)
void warning(const std::string &msg)
Exception(std::string msg)
GAUDIPS_API void SetDebug(int debugLevel)
Backward compatibility with Reflex.
GAUDIPS_API void setLogger(Logger *logger)
Set the logger instance to use.
static Registry & instance()
Retrieve the singleton instance of Registry.
In-memory database of the loaded factories.
FactoryInfo & add(const I &id, typename F::FuncType ptr)
Add a factory to the database.
virtual const char * what() const
std::map< KeyType, FactoryInfo > FactoryMap
Type used for the database implementation.
FactoryMap m_factories
Internal storage for factories.
Helper functions to set/get the application return code.
bool m_initialized
Flag recording if the registry has been initialized or not.
void debug(const std::string &msg)