• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "plugin_registry.h"
17 
18 #include <algorithm>
19 
20 #include <base/util/uid_util.h>
21 #include <core/log.h>
22 #include <core/plugin/intf_plugin_decl.h>
23 
24 #include "io/file_manager.h"
25 #include "io/path_tools.h"
26 #include "io/std_filesystem.h"
27 #include "os/intf_library.h"
28 #include "static_plugin_decl.h"
29 
30 CORE_BEGIN_NAMESPACE()
31 using BASE_NS::array_view;
32 using BASE_NS::move;
33 using BASE_NS::pair;
34 using BASE_NS::reverse_iterator;
35 using BASE_NS::string;
36 using BASE_NS::string_view;
37 using BASE_NS::to_string;
38 using BASE_NS::Uid;
39 using BASE_NS::vector;
40 
41 IInterface* CreateFileMonitor(CORE_NS::IClassFactory& registry, CORE_NS::PluginToken token);
42 IInterface* GetFileApiFactory(CORE_NS::IClassRegister& registry, CORE_NS::PluginToken token);
43 
44 namespace StaticPluginRegistry {
45 // static_plugin_registry magic begin
46 #if defined(CORE_USE_COMPILER_GENERATED_STATIC_LIST) && (CORE_USE_COMPILER_GENERATED_STATIC_LIST == 1)
47 
48 #if _MSC_VER
49 #pragma section("spd$b", long, read)
50 #pragma section("spd$d", long, read)
51 #pragma section("spd$e", long, read)
52 __declspec(allocate("spd$b")) static constexpr const IPlugin* g_staticPluginList = nullptr;
53 __declspec(allocate("spd$e")) static constexpr const IPlugin* g_staticPluginListEnd = nullptr;
54 #else
55 // clang-format off
56 __asm__(
57     ".pushsection " SECTION(spl.1)
58     " .local g_staticPluginList\n"
59     " g_staticPluginList:\n"
60     ".dc.a 0x0\n"
61     ".section " SECTION(spl.2)
62     " .local g_staticPluginListData\n"
63     "g_staticPluginListData:\n"
64     " .dc.a 0x0\n"
65     " .section " SECTION(spl.3)
66     " .local g_staticPluginListEnd\n"
67     " g_staticPluginListEnd:\n"
68     ".dc.a 0x0\n"
69     " .popsection\n");
70 // clang-format on
71 extern "C" {
72 extern CORE_NS::IPlugin const* const g_staticPluginList;
73 extern CORE_NS::IPlugin const* const g_staticPluginListData;
74 extern CORE_NS::IPlugin const* const g_staticPluginListEnd;
75 __attribute__((used)) CORE_NS::IPlugin const* const g_staticPluginListDataRef = g_staticPluginListData;
76 }
77 #endif
78 
79 #else
80 
81 #if _MSC_VER
82 static CORE_NS::IPlugin const* const* g_staticPluginList = nullptr;
83 static size_t g_staticPluginListCount = 0;
84 #else
85 __attribute__((visibility("hidden"))) static CORE_NS::IPlugin const* const* g_staticPluginList = nullptr;
86 __attribute__((visibility("hidden"))) static size_t g_staticPluginListCount = 0;
87 #endif
88 
89 void RegisterStaticPlugin(const CORE_NS::IPlugin& plugin)
90 {
91     static BASE_NS::vector<const CORE_NS::IPlugin*> gGlobalPlugins;
92     gGlobalPlugins.push_back(&plugin);
93     g_staticPluginList = gGlobalPlugins.data();
94     g_staticPluginListCount = gGlobalPlugins.size();
95 }
96 #endif
97 } // namespace StaticPluginRegistry
98 
99 namespace {
100 struct LibPlugin {
101     ILibrary::Ptr lib;
102     const IPlugin* plugin;
103 };
104 
105 template<typename Container, typename Predicate>
FindIf(const Container & container,Predicate && predicate)106 inline typename Container::const_iterator FindIf(const Container& container, Predicate&& predicate)
107 {
108     return std::find_if(container.cbegin(), container.cend(), BASE_NS::forward<Predicate>(predicate));
109 }
110 
111 template<typename Container, typename Predicate>
NoneOf(const Container & container,Predicate && predicate)112 inline bool NoneOf(const Container& container, Predicate&& predicate)
113 {
114     return std::none_of(container.cbegin(), container.cend(), BASE_NS::forward<Predicate>(predicate));
115 }
116 
117 template<typename Container, typename Predicate>
AllOf(const Container & container,Predicate && predicate)118 inline bool AllOf(const Container& container, Predicate&& predicate)
119 {
120     return std::all_of(container.cbegin(), container.cend(), BASE_NS::forward<Predicate>(predicate));
121 }
122 
GatherStaticPlugins(vector<LibPlugin> & plugins)123 void GatherStaticPlugins(vector<LibPlugin>& plugins)
124 {
125     CORE_LOG_V("Static plugins:");
126 #if defined(CORE_USE_COMPILER_GENERATED_STATIC_LIST) && (CORE_USE_COMPILER_GENERATED_STATIC_LIST == 1)
127     const array_view<const IPlugin* const> staticPluginRegistry(
128         &StaticPluginRegistry::g_staticPluginList, &StaticPluginRegistry::g_staticPluginListEnd);
129 #else
130     const array_view<const IPlugin* const> staticPluginRegistry(
131         StaticPluginRegistry::g_staticPluginList, StaticPluginRegistry::g_staticPluginListCount);
132 #endif
133 
134     for (const auto plugin : staticPluginRegistry) {
135         if (plugin && (plugin->typeUid == IPlugin::UID)) {
136             CORE_LOG_V("\t%s", plugin->name);
137             plugins.push_back({ nullptr, plugin });
138         }
139     }
140 }
141 
GatherDynamicPlugins(vector<LibPlugin> & plugins,IFileManager & fileManager)142 void GatherDynamicPlugins(vector<LibPlugin>& plugins, IFileManager& fileManager)
143 {
144     CORE_LOG_V("Dynamic plugins:");
145     const auto libraryFileExtension = ILibrary::GetFileExtension();
146     constexpr string_view pluginRoot { "plugins://" };
147     IDirectory::Ptr pluginFiles = fileManager.OpenDirectory(pluginRoot);
148     for (const auto& file : pluginFiles->GetEntries()) {
149         const string_view pluginFile = file.name;
150         if (pluginFile.substr(file.name.length() - libraryFileExtension.size()) == libraryFileExtension) {
151             const string absoluteFile = fileManager.GetEntry(pluginRoot + file.name).name;
152             ILibrary::Ptr lib = ILibrary::Load(absoluteFile);
153             if (lib == nullptr) {
154                 continue;
155             }
156             const IPlugin* plugin = lib->GetPlugin();
157             if (plugin && (plugin->typeUid == IPlugin::UID)) {
158                 CORE_LOG_V("\t%s", plugin->name);
159                 plugins.push_back({ move(lib), plugin });
160             }
161         }
162     }
163 }
164 
Notify(const array_view<IPluginRegister::ITypeInfoListener * > listeners,IPluginRegister::ITypeInfoListener::EventType type,array_view<const ITypeInfo * const> typeInfos)165 void Notify(const array_view<IPluginRegister::ITypeInfoListener*> listeners,
166     IPluginRegister::ITypeInfoListener::EventType type, array_view<const ITypeInfo* const> typeInfos)
167 {
168     for (IPluginRegister::ITypeInfoListener* listener : listeners) {
169         if (listener) {
170             listener->OnTypeInfoEvent(type, typeInfos);
171         }
172     }
173 }
174 } // namespace
175 
RegisterGlobalInterfaces(PluginRegistry & registry)176 vector<InterfaceTypeInfo> PluginRegistry::RegisterGlobalInterfaces(PluginRegistry& registry)
177 {
178     vector<InterfaceTypeInfo> interfaces = {
179         InterfaceTypeInfo { &registry, UID_LOGGER, GetName<ILogger>().data(), nullptr,
180             [](IClassRegister& registry, PluginToken token) -> IInterface* {
181                 return &static_cast<PluginRegistry*>(token)->logger_;
182             } },
183         InterfaceTypeInfo { &registry, UID_FRUSTUM_UTIL, GetName<IFrustumUtil>().data(), nullptr,
184             [](IClassRegister& registry, PluginToken token) -> IInterface* {
185                 return &static_cast<PluginRegistry*>(token)->frustumUtil_;
186             } },
187         InterfaceTypeInfo { &registry, UID_ENGINE_FACTORY, GetName<IEngineFactory>().data(), nullptr,
188             [](IClassRegister& registry, PluginToken token) -> IInterface* {
189                 return static_cast<PluginRegistry*>(token)->engineFactory_.GetInterface(IEngineFactory::UID);
190             } },
191         InterfaceTypeInfo { &registry, UID_SYSTEM_GRAPH_LOADER, GetName<ISystemGraphLoaderFactory>().data(), nullptr,
192             [](IClassRegister& registry, PluginToken token) -> IInterface* {
193                 return &static_cast<PluginRegistry*>(token)->systemGraphLoadeFactory;
194             } },
195         InterfaceTypeInfo { &registry, UID_GLOBAL_FACTORY, "Global registry factory", nullptr,
196             [](IClassRegister& registry, PluginToken token) -> IInterface* {
197                 return registry.GetInterface<IClassFactory>();
198             } },
199         InterfaceTypeInfo {
200             &registry, UID_FILESYSTEM_API_FACTORY, "Filesystem API factory", nullptr, GetFileApiFactory },
201         InterfaceTypeInfo { &registry, UID_FILE_MONITOR, "Filemonitor", CreateFileMonitor, nullptr },
202         InterfaceTypeInfo { &registry, UID_FILE_MANAGER, "FileManager",
203             [](IClassFactory& factory, PluginToken token) -> IInterface* { return new CORE_NS::FileManager(); },
204             nullptr },
205         InterfaceTypeInfo { &registry, UID_TASK_QUEUE_FACTORY, "Task queue factory", nullptr,
206             [](IClassRegister& registry, PluginToken token) -> IInterface* {
207                 return &static_cast<PluginRegistry*>(token)->taskQueueFactory_;
208             } },
209 #if (CORE_PERF_ENABLED == 1)
210         InterfaceTypeInfo { &registry, UID_PERFORMANCE_FACTORY, GetName<IPerformanceDataManagerFactory>().data(),
211             nullptr,
212             [](IClassRegister& registry, PluginToken token) -> IInterface* {
213                 return &static_cast<PluginRegistry*>(token)->perfManFactory_;
214             } }
215 #endif
216     };
217 
218     for (const auto& info : interfaces) {
219         registry.RegisterInterfaceType(info);
220     }
221     return interfaces;
222 }
223 
UnregisterGlobalInterfaces()224 void PluginRegistry::UnregisterGlobalInterfaces()
225 {
226     for (const auto& info : ownInterfaceInfos_) {
227         RegisterInterfaceType(info);
228     }
229 }
230 
PluginRegistry()231 PluginRegistry::PluginRegistry() : ownInterfaceInfos_(RegisterGlobalInterfaces(*this)) {}
232 
~PluginRegistry()233 PluginRegistry::~PluginRegistry()
234 {
235     UnloadPlugins({});
236     UnregisterGlobalInterfaces();
237 }
238 
239 // IPluginRegister
GetPlugins() const240 array_view<const IPlugin* const> PluginRegistry::GetPlugins() const
241 {
242     return plugins_;
243 }
244 
LoadPlugins(const array_view<const Uid> pluginUids)245 bool PluginRegistry::LoadPlugins(const array_view<const Uid> pluginUids)
246 {
247     // Gather all the available static and dynamic libraries.
248     vector<LibPlugin> plugins;
249     GatherStaticPlugins(plugins);
250     GatherDynamicPlugins(plugins, fileManager_);
251 
252     // If a list of UIDs was given remove all except the requires plugins.
253     if (!pluginUids.empty()) {
254         // Gather dependencies of each plugin.
255         vector<Uid> toLoad;
256         toLoad.reserve(plugins.size());
257 
258         auto addDependencies = [](auto&& addDependencies, vector<Uid>& toBeLoaded,
259                                    const vector<LibPlugin>& availablePlugins,
260                                    BASE_NS::vector<const IPlugin*>& loadedPlugins, const Uid& uidToLoad) -> bool {
261             bool found = true;
262             // Only consider plugins which are not already loaded, and not yet in the loading list.
263             if (NoneOf(
264                     loadedPlugins, [&uidToLoad](const IPlugin* loaded) { return loaded->version.uid == uidToLoad; }) &&
265                 NoneOf(toBeLoaded, [&uidToLoad](const Uid& willLoad) { return willLoad == uidToLoad; })) {
266                 if (auto pos = FindIf(availablePlugins,
267                         [&uidToLoad](
268                             const LibPlugin& libPlugin) { return libPlugin.plugin->version.uid == uidToLoad; });
269                     pos != availablePlugins.end()) {
270                     found = AllOf(pos->plugin->pluginDependencies, [&](const Uid& dependency) {
271                         return addDependencies(
272                             addDependencies, toBeLoaded, availablePlugins, loadedPlugins, dependency);
273                     });
274                     if (found) {
275                         toBeLoaded.push_back(uidToLoad);
276                     }
277                 } else {
278                     found = false;
279                 }
280             }
281             return found;
282         };
283         const bool found = AllOf(pluginUids,
284             [&](const Uid& uid) { return addDependencies(addDependencies, toLoad, plugins, plugins_, uid); });
285 
286         // Order the available plugins to match the to-be-loaded list and remove extras.
287         auto begin = plugins.begin();
288         auto end = plugins.end();
289         for (const Uid& uid : toLoad) {
290             if (auto pos = std::find_if(
291                     begin, end, [uid](const LibPlugin& libPlugin) { return libPlugin.plugin->version.uid == uid; });
292                 pos != end) {
293                 std::rotate(begin, pos, end);
294                 ++begin;
295             }
296         }
297         plugins.erase(begin, end);
298 
299         if (!found) {
300             CORE_LOG_E("Unable to load plugins:");
301             for (const auto& uid : pluginUids) {
302                 if (NoneOf(plugins, [uid](const auto& available) { return available.plugin->version.uid == uid; })) {
303                     CORE_LOG_E("\t%s", to_string(uid).data());
304                 }
305             }
306             return false;
307         }
308     }
309 
310     // Now we should have only the desired plugins and can load all of them.
311     CORE_LOG_D("Load plugins:");
312     loading_ = true;
313     for (auto& plugin : plugins) {
314         RegisterPlugin(move(plugin.lib), *plugin.plugin);
315     }
316     loading_ = false;
317 
318     if (!newTypeInfos_.empty()) {
319         Notify(typeInfoListeners_, ITypeInfoListener::EventType::ADDED, newTypeInfos_);
320         newTypeInfos_.clear();
321     }
322 
323     return true;
324 }
325 
UnloadPlugins(const array_view<const Uid> pluginUids)326 void PluginRegistry::UnloadPlugins(const array_view<const Uid> pluginUids)
327 {
328     CORE_LOG_D("Unload plugins:");
329     if (pluginUids.empty()) {
330         auto pdIt = pluginDatas_.rbegin();
331         for (auto pos = plugins_.rbegin(), last = plugins_.rend(); pos != last; ++pos) {
332             UnregisterPlugin(*(*pos), pdIt->token);
333             ++pdIt;
334         }
335         plugins_.clear();
336         pluginDatas_.clear();
337     } else {
338         for (const auto& uid : pluginUids) {
339             if (auto pos = std::find_if(plugins_.begin(), plugins_.end(),
340                     [uid](const IPlugin* pl) { return pl && pl->version.uid == uid; });
341                 pos != plugins_.end()) {
342                 const auto index = static_cast<size_t>(std::distance(plugins_.begin(), pos));
343                 --pluginDatas_[index].refcnt;
344 
345                 for (const auto& dependency : (*pos)->pluginDependencies) {
346                     if (const auto depPos = std::find_if(plugins_.begin(), plugins_.end(),
347                             [dependency](const IPlugin* plugin) { return plugin->version.uid == dependency; });
348                         depPos != plugins_.end()) {
349                         const auto depIndex = static_cast<size_t>(std::distance(plugins_.begin(), depPos));
350                         --pluginDatas_[depIndex].refcnt;
351                     }
352                 }
353             }
354         }
355         auto pdIt = pluginDatas_.rbegin();
356         for (auto pos = plugins_.rbegin(), last = plugins_.rend(); pos != last;) {
357             if (pdIt->refcnt == 0) {
358                 UnregisterPlugin(*(*pos), pdIt->token);
359                 plugins_.erase(pos.base() - 1);
360                 pluginDatas_.erase(pdIt.base() - 1);
361             }
362             ++pos;
363             ++pdIt;
364         }
365     }
366 }
367 
GetClassRegister() const368 IClassRegister& PluginRegistry::GetClassRegister() const
369 {
370     return *const_cast<PluginRegistry*>(this);
371 }
372 
RegisterTypeInfo(const ITypeInfo & type)373 void PluginRegistry::RegisterTypeInfo(const ITypeInfo& type)
374 {
375     if (const auto pos = typeInfos_.find(type.typeUid); pos != typeInfos_.cend()) {
376         pos->second.emplace_back(&type);
377     } else {
378         typeInfos_.insert({ type.typeUid, {} }).first->second.emplace_back(&type);
379     }
380 
381     // During plugin loading gather all the infos and send events once.
382     if (loading_) {
383         newTypeInfos_.push_back(&type);
384     } else {
385         const ITypeInfo* const infos[] = { &type };
386         Notify(typeInfoListeners_, ITypeInfoListener::EventType::ADDED, infos);
387     }
388 }
389 
UnregisterTypeInfo(const ITypeInfo & type)390 void PluginRegistry::UnregisterTypeInfo(const ITypeInfo& type)
391 {
392     if (const auto typeInfos = typeInfos_.find(type.typeUid); typeInfos != typeInfos_.cend()) {
393         auto& infos = typeInfos->second;
394         if (const auto info = std::find(infos.begin(), infos.end(), &type); info != infos.end()) {
395             infos.erase(info);
396         }
397     }
398 
399     const ITypeInfo* const infos[] = { &type };
400     Notify(typeInfoListeners_, ITypeInfoListener::EventType::REMOVED, infos);
401 }
402 
GetTypeInfos(const Uid & typeUid) const403 array_view<const ITypeInfo* const> PluginRegistry::GetTypeInfos(const Uid& typeUid) const
404 {
405     if (const auto typeInfos = typeInfos_.find(typeUid); typeInfos != typeInfos_.cend()) {
406         return typeInfos->second;
407     }
408     return {};
409 }
410 
AddListener(ITypeInfoListener & listener)411 void PluginRegistry::AddListener(ITypeInfoListener& listener)
412 {
413     if (std::none_of(typeInfoListeners_.begin(), typeInfoListeners_.end(),
414             [adding = &listener](const auto& current) { return current == adding; })) {
415         typeInfoListeners_.push_back(&listener);
416     }
417 }
418 
RemoveListener(const ITypeInfoListener & listener)419 void PluginRegistry::RemoveListener(const ITypeInfoListener& listener)
420 {
421     if (auto pos = std::find(typeInfoListeners_.begin(), typeInfoListeners_.end(), &listener);
422         pos != typeInfoListeners_.end()) {
423         *pos = nullptr;
424     }
425 }
426 
427 // IClassRegister
RegisterInterfaceType(const InterfaceTypeInfo & interfaceInfo)428 void PluginRegistry::RegisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
429 {
430     // keep interfaceTypeInfos_ sorted according to UIDs
431     const auto pos = std::upper_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
432         [](Uid value, const InterfaceTypeInfo* element) { return value < element->uid; });
433     interfaceTypeInfos_.insert(pos, &interfaceInfo);
434 }
435 
UnregisterInterfaceType(const InterfaceTypeInfo & interfaceInfo)436 void PluginRegistry::UnregisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
437 {
438     if (!interfaceTypeInfos_.empty()) {
439         const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
440             [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
441         if ((pos != interfaceTypeInfos_.cend()) && (*pos) && (*pos)->uid == interfaceInfo.uid) {
442             interfaceTypeInfos_.erase(pos);
443         }
444     }
445 }
446 
GetInterfaceMetadata() const447 array_view<const InterfaceTypeInfo* const> PluginRegistry::GetInterfaceMetadata() const
448 {
449     return { interfaceTypeInfos_.data(), interfaceTypeInfos_.size() };
450 }
451 
GetInterfaceMetadata(const Uid & uid) const452 const InterfaceTypeInfo& PluginRegistry::GetInterfaceMetadata(const Uid& uid) const
453 {
454     static InterfaceTypeInfo invalidType {};
455 
456     if (!interfaceTypeInfos_.empty()) {
457         const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), uid,
458             [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
459         if ((pos != interfaceTypeInfos_.cend()) && (*pos) && (*pos)->uid == uid) {
460             return *(*pos);
461         }
462     }
463     return invalidType;
464 }
465 
GetInstance(const Uid & uid) const466 IInterface* PluginRegistry::GetInstance(const Uid& uid) const
467 {
468     const auto& data = GetInterfaceMetadata(uid);
469     if (data.getInterface) {
470         return data.getInterface(const_cast<PluginRegistry&>(*this), data.token);
471     }
472     return nullptr;
473 }
474 
475 // IClassFactory
CreateInstance(const Uid & uid)476 IInterface::Ptr PluginRegistry::CreateInstance(const Uid& uid)
477 {
478     const auto& data = GetInterfaceMetadata(uid);
479     if (data.createInterface) {
480         return IInterface::Ptr { data.createInterface(*this, data.token) };
481     }
482     return {};
483 }
484 
485 // IInterface
GetInterface(const Uid & uid) const486 const IInterface* PluginRegistry::GetInterface(const Uid& uid) const
487 {
488     return const_cast<PluginRegistry*>(this)->GetInterface(uid);
489 }
490 
GetInterface(const Uid & uid)491 IInterface* PluginRegistry::GetInterface(const Uid& uid)
492 {
493     if ((uid == IInterface::UID) || (uid == IClassRegister::UID)) {
494         return static_cast<IClassRegister*>(this);
495     }
496     if (uid == IClassFactory::UID) {
497         return static_cast<IClassFactory*>(this);
498     }
499     return nullptr;
500 }
501 
Ref()502 void PluginRegistry::Ref() {}
503 
Unref()504 void PluginRegistry::Unref() {}
505 
506 // Public members
RegisterPluginPath(const string_view path)507 void PluginRegistry::RegisterPluginPath(const string_view path)
508 {
509     if (!fileProtocolRegistered_) {
510         fileProtocolRegistered_ = true;
511         fileManager_.RegisterFilesystem("file", IFilesystem::Ptr { new StdFilesystem("/") });
512     }
513     fileManager_.RegisterPath("plugins", path, false);
514 }
515 
GetFileManager()516 IFileManager& PluginRegistry::GetFileManager()
517 {
518     return fileManager_;
519 }
520 
521 // Private members
RegisterPlugin(ILibrary::Ptr lib,const IPlugin & plugin)522 void PluginRegistry::RegisterPlugin(ILibrary::Ptr lib, const IPlugin& plugin)
523 {
524     CORE_LOG_D("\tRegister Plugin: %s %s", plugin.name, to_string(plugin.version.uid).data());
525     if (plugin.version.GetVersionString) {
526         CORE_LOG_D("\tVersion Info: %s", plugin.version.GetVersionString());
527     }
528     if (std::any_of(plugins_.begin(), plugins_.end(),
529             [&plugin](const IPlugin* pl) { return strcmp(plugin.name, pl->name) == 0; })) {
530         CORE_LOG_W("\tSkipping duplicate plugin: %s!", plugin.name);
531         return;
532     }
533     PluginData pd { move(lib), {}, 1U };
534     if (plugin.registerInterfaces) {
535         pd.token = plugin.registerInterfaces(*this);
536     }
537 
538     pluginDatas_.push_back(move(pd));
539     plugins_.push_back(&plugin);
540     for (const auto& dependency : plugin.pluginDependencies) {
541         if (auto pos = std::find_if(plugins_.begin(), plugins_.end(),
542                 [dependency](const IPlugin* plugin) { return plugin->version.uid == dependency; });
543             pos != plugins_.end()) {
544             const auto index = static_cast<size_t>(std::distance(plugins_.begin(), pos));
545             ++pluginDatas_[index].refcnt;
546         }
547     }
548 }
549 
UnregisterPlugin(const IPlugin & pd,PluginToken token)550 void PluginRegistry::UnregisterPlugin(const IPlugin& pd, PluginToken token)
551 {
552     CORE_LOG_D("\tUnregister Plugin: %s %s", pd.name, to_string(pd.version.uid).data());
553 
554     if (pd.unregisterInterfaces) {
555         pd.unregisterInterfaces(token);
556     }
557 }
558 
559 // Library exports
GetPluginRegister()560 CORE_PUBLIC IPluginRegister& GetPluginRegister()
561 {
562     static PluginRegistry registry;
563     return registry;
564 }
565 
CreatePluginRegistry(const PlatformCreateInfo & platformCreateInfo)566 CORE_PUBLIC void CreatePluginRegistry(const PlatformCreateInfo& platformCreateInfo)
567 {
568     static bool once = false;
569     if (!once) {
570         once = true;
571         auto& registry = static_cast<PluginRegistry&>(GetPluginRegister());
572         // Create plugins:// protocol that points to plugin files.
573         // register path to system plugins
574         // Root path is the location where system plugins , non-rofs assets etc could be held.
575         auto platform = Platform::Create(platformCreateInfo);
576         platform->RegisterPluginLocations(registry);
577     }
578 }
579 CORE_END_NAMESPACE()
580