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 { ®istry, UID_LOGGER, GetName<ILogger>().data(), nullptr,
180 [](IClassRegister& registry, PluginToken token) -> IInterface* {
181 return &static_cast<PluginRegistry*>(token)->logger_;
182 } },
183 InterfaceTypeInfo { ®istry, UID_FRUSTUM_UTIL, GetName<IFrustumUtil>().data(), nullptr,
184 [](IClassRegister& registry, PluginToken token) -> IInterface* {
185 return &static_cast<PluginRegistry*>(token)->frustumUtil_;
186 } },
187 InterfaceTypeInfo { ®istry, 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 { ®istry, UID_SYSTEM_GRAPH_LOADER, GetName<ISystemGraphLoaderFactory>().data(), nullptr,
192 [](IClassRegister& registry, PluginToken token) -> IInterface* {
193 return &static_cast<PluginRegistry*>(token)->systemGraphLoadeFactory;
194 } },
195 InterfaceTypeInfo { ®istry, UID_GLOBAL_FACTORY, "Global registry factory", nullptr,
196 [](IClassRegister& registry, PluginToken token) -> IInterface* {
197 return registry.GetInterface<IClassFactory>();
198 } },
199 InterfaceTypeInfo {
200 ®istry, UID_FILESYSTEM_API_FACTORY, "Filesystem API factory", nullptr, GetFileApiFactory },
201 InterfaceTypeInfo { ®istry, UID_FILE_MONITOR, "Filemonitor", CreateFileMonitor, nullptr },
202 InterfaceTypeInfo { ®istry, UID_FILE_MANAGER, "FileManager",
203 [](IClassFactory& factory, PluginToken token) -> IInterface* { return new CORE_NS::FileManager(); },
204 nullptr },
205 InterfaceTypeInfo { ®istry, 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 { ®istry, 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