14 #define GAUDI_PLUGIN_SERVICE_V2 36 namespace fs = std::filesystem;
38 #include <experimental/filesystem> 39 namespace fs = std::experimental::filesystem;
42 #if __cplusplus >= 201703 43 #include <string_view> 45 #include <experimental/string_view> 48 using experimental::string_view;
52 #define REG_SCOPE_LOCK std::lock_guard<std::recursive_mutex> _guard( m_mutex ); 58 #define SINGLETON_LOCK std::lock_guard<std::mutex> _guard(::registrySingletonMutex ); 101 namespace PluginService
111 abi::__cxa_demangle(
id.c_str(),
nullptr,
nullptr, &status ),
free );
112 if ( !realname )
return id;
113 #if _GLIBCXX_USE_CXX11_ABI 116 std::regex{
"std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >( (?=>))?"},
124 Registry& Registry::instance()
135 const auto& info = Registry::instance().getInfo(
id );
136 msg <<
"bad any_cast: requested factory " <<
id <<
" of type " <<
demangle( factory_type ) <<
", got ";
138 msg <<
demangle( info.factory.type() ) <<
" from " << info.library;
145 Registry::Properties::mapped_type Registry::FactoryInfo::getprop(
const Properties::key_type&
name )
const 148 return ( p !=
end(
properties ) ) ? p->second : Properties::mapped_type{};
151 Registry::Registry() {}
153 void Registry::initialize()
156 #if defined( _WIN32 ) 157 const char* envVar =
"PATH";
158 const char sep =
';';
159 #elif defined( __APPLE__ ) 160 const char* envVar =
"DYLD_LIBRARY_PATH";
161 const char sep =
':';
163 const char* envVar =
"LD_LIBRARY_PATH";
164 const char sep =
':';
167 std::regex line_format{
"^(?:[[:space:]]*(?:(v[0-9]+)::)?([^:]+):(.*[^[:space:]]))?[[:space:]]*(?:#.*)?$"};
170 std::string_view search_path =
std::getenv( envVar );
171 if ( !search_path.empty() ) {
174 std::string_view::size_type start_pos = 0, end_pos = 0;
175 while ( start_pos != std::string_view::npos ) {
177 if ( start_pos ) ++start_pos;
179 end_pos = search_path.find( sep, start_pos );
182 search_path.substr( start_pos, end_pos - start_pos );
188 logger().debug(
" looking into " + dirName.string() );
190 if ( is_directory( dirName ) ) {
191 for (
auto& p : fs::directory_iterator( dirName ) ) {
192 if ( p.path().extension() ==
".components" && is_regular_file( p.path() ) ) {
194 const auto& fullPath = p.path().string();
195 logger().debug(
" reading " + p.path().filename().string() );
198 int factoriesCount = 0;
204 if ( m[1] ==
"v2" ) {
207 m_factories.emplace( fact, FactoryInfo{lib, {}, {{
"ClassName", fact}}} );
208 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES 211 if ( fact != old_name ) {
212 m_factories.emplace( old_name,
213 FactoryInfo{lib, {}, {{
"ReflexName",
"true"}, {
"ClassName", fact}}} );
234 std::call_once( m_initialized, &Registry::initialize, const_cast<Registry*>(
this ) );
240 std::call_once( m_initialized, &Registry::initialize, const_cast<Registry*>(
this ) );
244 Registry::FactoryInfo&
Registry::add(
const KeyType&
id, FactoryInfo info )
249 #ifdef GAUDI_REFLEX_COMPONENT_ALIASES 251 const auto old_name = old_style_name(
id );
252 if (
id != old_name ) {
253 auto new_info = info;
255 new_info.properties[
"ReflexName"] =
"true";
257 add( old_name, new_info );
261 auto entry = facts.find(
id );
262 if ( entry == facts.end() ) {
264 entry = facts.emplace(
id,
std::move( info ) ).first;
267 if ( !entry->second.is_set() ) entry->second =
std::move( info );
269 return entry->second;
272 const Registry::FactoryInfo& Registry::getInfo(
const KeyType&
id,
const bool load )
const 275 static const FactoryInfo unknown = {
"unknown"};
277 auto f = facts.find(
id );
279 if ( f != facts.end() ) {
280 if ( load && !f->second.is_set() ) {
281 if ( !dlopen( f->second.library.c_str(), RTLD_LAZY | RTLD_GLOBAL ) ) {
282 logger().warning(
"cannot load " + f->second.library +
" for factory " +
id );
283 char* dlmsg = dlerror();
284 if ( dlmsg )
logger().warning( dlmsg );
287 f = facts.find(
id );
295 Registry& Registry::addProperty(
const KeyType&
id,
const KeyType& k,
const std::string& v )
299 auto f = facts.find(
id );
301 if ( f != facts.end() ) f->second.properties[k] = v;
310 if ( f.second.is_set() ) l.insert( f.first );
317 static const char* levels[] = {
"DEBUG : ",
"INFO : ",
"WARNING: ",
"ERROR : "};
318 if ( lvl >=
level() ) {
323 static auto s_logger = std::make_unique<Logger>();
332 if ( dladdr( fptr, &info ) == 0 )
return "";
338 return info.dli_fname;
348 using namespace Details;
350 if ( debugLevel > 1 )
352 else if ( debugLevel > 0 )
353 l.setLevel( Logger::Info );
355 l.setLevel( Logger::Warning );
360 using namespace Details;
#define GAUDI_PLUGIN_SERVICE_V2_INLINE
void SetDebug(int debugLevel)
std::string getDSONameFor(void *fptr)
void reportBadAnyCast(const std::type_info &factory_type, const std::string &id)
T regex_replace(T...args)
std::string demangle(const std::type_info &id)
void setLogger(Logger *logger)
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
Helper functions to set/get the application return code.