14 #define GAUDI_PLUGIN_SERVICE_V1 29 #define REG_SCOPE_LOCK std::lock_guard<std::recursive_mutex> _guard( m_mutex ); 35 #define SINGLETON_LOCK std::lock_guard<std::mutex> _guard(::registrySingletonMutex ); 44 constexpr
struct is_space_t {
75 }
else if ( dest != value ) {
77 ": " + dest +
" != " + value );
118 namespace PluginService
130 return Registry::instance().get(
id, type );
137 abi::__cxa_demangle(
id.c_str(),
nullptr,
nullptr, &status ), free );
138 if ( !realname )
return id;
139 #if _GLIBCXX_USE_CXX11_ABI 142 std::regex{
"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >( (?=>))?"},
157 Registry::Registry() : m_initialized( false ) {}
164 #if defined( _WIN32 ) 165 const char* envVar =
"PATH";
166 const char sep =
';';
167 #elif defined( __APPLE__ ) 168 const char* envVar =
"DYLD_LIBRARY_PATH";
169 const char sep =
':';
171 const char* envVar =
"LD_LIBRARY_PATH";
172 const char sep =
':';
174 char* search_path = ::getenv( envVar );
178 std::string::size_type pos = 0;
179 std::string::size_type newpos = 0;
180 while ( pos != std::string::npos ) {
183 newpos = path.
find( sep, pos );
184 if ( newpos != std::string::npos ) {
185 dirName = path.
substr( pos, newpos - pos );
188 dirName = path.
substr( pos );
193 DIR* dir = opendir( dirName.
c_str() );
195 struct dirent* entry;
196 while ( ( entry = readdir( dir ) ) ) {
199 std::string::size_type extpos = name.
find(
".components" );
200 if ( ( extpos != std::string::npos ) && ( ( extpos + 11 ) == name.
size() ) ) {
204 stat( fullPath.
c_str(), &buf );
205 if ( !S_ISREG( buf.st_mode ) )
continue;
211 int factoriesCount = 0;
218 if ( line.
empty() || line[0] ==
'#' )
continue;
220 if ( line.
substr( 0, 4 ) ==
"v1::" )
225 auto pos = line.
find(
':' );
226 if ( pos == std::string::npos ) {
233 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES 236 if ( fact != old_name ) {
261 auto entry = facts.find(
id );
262 if ( entry == facts.end() ) {
264 entry = facts.emplace(
id,
FactoryInfo(
"unknown", factory, type, rtype, className, props ) ).first;
267 if ( !entry->second.ptr ) entry->second.ptr = factory;
268 factoryInfoSetHelper( entry->second.type, type,
"type",
id );
269 factoryInfoSetHelper( entry->second.rtype, rtype,
"return type",
id );
270 factoryInfoSetHelper( entry->second.className, className,
"class",
id );
272 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES 275 if (
id != old_name )
276 add( old_name, factory, type, rtype, className, props ).
properties[
"ReflexName"] =
"true";
278 return entry->second;
285 auto f = facts.find(
id );
286 if ( f != facts.end() ) {
287 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES 288 const Properties& props = f->second.properties;
289 if ( props.
find(
"ReflexName" ) != props.
end() )
290 logger().
warning(
"requesting factory via old name '" +
id +
"'" 292 f->second.className +
"' instead" );
294 if ( !f->second.ptr ) {
295 if ( !dlopen( f->second.library.c_str(), RTLD_LAZY | RTLD_GLOBAL ) ) {
296 logger().
warning(
"cannot load " + f->second.library +
" for factory " +
id );
297 char* dlmsg = dlerror();
301 f = facts.find(
id );
303 if ( f->second.type == type )
return f->second.ptr;
305 " instead of " +
demangle( type ) );
315 auto f = facts.
find(
id );
316 return ( f != facts.
end() ) ? f->second : unknown;
323 auto f = facts.find(
id );
324 if ( f != facts.end() ) f->second.properties[k] = v;
333 if ( f.second.ptr ) l.insert( f.first );
340 static const char* levels[] = {
"DEBUG : ",
"INFO : ",
"WARNING: ",
"ERROR : "};
341 if ( lvl >=
level() ) {
346 static auto s_logger = std::make_unique<Logger>();
354 using namespace Details;
356 if ( debugLevel > 1 )
358 else if ( debugLevel > 0 )
366 using namespace Details;
FactoryInfo & add(const I &id, typename F::FuncType ptr)
Add a factory to the database.
GAUDIPS_API void * getCreator(const std::string &id, const std::string &type)
Function used to load a specific factory function.
virtual void report(Level lvl, const std::string &msg)
Simple logging class, just to provide a default implementation.
FactoryMap m_factories
Internal storage for factories.
std::string demangle(const std::string &id)
GAUDIPS_API void setLogger(Logger *logger)
Set the logger instance to use.
void debug(const std::string &msg)
#define GAUDI_PLUGIN_SERVICE_V1_INLINE
void warning(const std::string &msg)
const FactoryMap & factories() const
Return the known factories (loading the list if not yet done).
GAUDIPS_API Logger & logger()
Return the current logger instance.
T regex_replace(T...args)
In-memory database of the loaded factories.
void * get(const std::string &id, const std::string &type) const
Retrieve the factory for the given id.
GAUDIPS_API int Debug()
Backward compatibility with Reflex.
GAUDIPS_API std::string demangle(const std::type_info &id)
Return a canonical name for type_info object (implementation borrowed from GaudiKernel/System).
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
std::set< KeyType > loadedFactoryNames() const
Return a list of all the known and loaded factories.
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.)
void initialize()
Initialize the registry loading the list of factories from the .component files in the library search...
GAUDIPS_API void SetDebug(int debugLevel)
Backward compatibility with Reflex.
const char * what() const override
const FactoryInfo & getInfo(const std::string &id) const
Retrieve the FactoryInfo object for an id.
Helper functions to set/get the application return code.
bool m_initialized
Flag recording if the registry has been initialized or not.