/src/WasmEdge/include/plugin/plugin.h
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | //===-- wasmedge/plugin/plugin.h - Plugin class definition ----------------===// |
5 | | // |
6 | | // Part of the WasmEdge Project. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | /// |
10 | | /// \file |
11 | | /// This file defines the Plugin class. |
12 | | /// |
13 | | //===----------------------------------------------------------------------===// |
14 | | #pragma once |
15 | | |
16 | | #include "common/defines.h" |
17 | | #include "common/filesystem.h" |
18 | | #include "common/hash.h" |
19 | | #include "common/version.h" |
20 | | #include "loader/shared_library.h" |
21 | | #include "po/argument_parser.h" |
22 | | #include "runtime/instance/component/component.h" |
23 | | #include "runtime/instance/module.h" |
24 | | |
25 | | #include <cstdint> |
26 | | #include <deque> |
27 | | #include <memory> |
28 | | #include <mutex> |
29 | | #include <shared_mutex> |
30 | | #include <vector> |
31 | | |
32 | | #define EXPORT_GET_DESCRIPTOR(Descriptor) \ |
33 | | extern "C" WASMEDGE_EXPORT decltype(&Descriptor) GetDescriptor(); \ |
34 | | extern "C" WASMEDGE_EXPORT decltype(&Descriptor) GetDescriptor() { \ |
35 | | return &Descriptor; \ |
36 | | } |
37 | | |
38 | | namespace WasmEdge { |
39 | | namespace Plugin { |
40 | | |
41 | | class PluginModule { |
42 | | public: |
43 | | PluginModule(const PluginModule &) = delete; |
44 | | PluginModule &operator=(const PluginModule &) = delete; |
45 | | PluginModule(PluginModule &&) noexcept = default; |
46 | | PluginModule &operator=(PluginModule &&) noexcept = default; |
47 | | |
48 | | struct ModuleDescriptor { |
49 | | const char *Name; |
50 | | const char *Description; |
51 | | Runtime::Instance::ModuleInstance *(*Create)( |
52 | | const ModuleDescriptor *) noexcept; |
53 | | }; |
54 | | |
55 | 0 | constexpr PluginModule() noexcept {} |
56 | | |
57 | 0 | constexpr const char *name() const noexcept { |
58 | 0 | assuming(Desc); |
59 | 0 | return Desc->Name; |
60 | 0 | } |
61 | | |
62 | 0 | constexpr const char *description() const noexcept { |
63 | 0 | assuming(Desc); |
64 | 0 | return Desc->Description; |
65 | 0 | } |
66 | | |
67 | 0 | std::unique_ptr<Runtime::Instance::ModuleInstance> create() const noexcept { |
68 | 0 | assuming(Desc); |
69 | 0 | return std::unique_ptr<Runtime::Instance::ModuleInstance>( |
70 | 0 | Desc->Create(Desc)); |
71 | 0 | } |
72 | | |
73 | | private: |
74 | | const ModuleDescriptor *Desc = nullptr; |
75 | | |
76 | | constexpr explicit PluginModule(const ModuleDescriptor *D) noexcept |
77 | 0 | : Desc(D) {} |
78 | | friend class Plugin; |
79 | | }; |
80 | | |
81 | | class PluginComponent { |
82 | | public: |
83 | | PluginComponent(const PluginComponent &) = delete; |
84 | | PluginComponent &operator=(const PluginComponent &) = delete; |
85 | | PluginComponent(PluginComponent &&) noexcept = default; |
86 | | PluginComponent &operator=(PluginComponent &&) noexcept = default; |
87 | | |
88 | | struct ComponentDescriptor { |
89 | | const char *Name; |
90 | | const char *Description; |
91 | | Runtime::Instance::ComponentInstance *(*Create)( |
92 | | const ComponentDescriptor *) noexcept; |
93 | | }; |
94 | | |
95 | 0 | constexpr PluginComponent() noexcept {} |
96 | | |
97 | 0 | constexpr const char *name() const noexcept { |
98 | 0 | assuming(Desc); |
99 | 0 | return Desc->Name; |
100 | 0 | } |
101 | | |
102 | 0 | constexpr const char *description() const noexcept { |
103 | 0 | assuming(Desc); |
104 | 0 | return Desc->Description; |
105 | 0 | } |
106 | | |
107 | | std::unique_ptr<Runtime::Instance::ComponentInstance> |
108 | 0 | create() const noexcept { |
109 | 0 | assuming(Desc); |
110 | 0 | return std::unique_ptr<Runtime::Instance::ComponentInstance>( |
111 | 0 | Desc->Create(Desc)); |
112 | 0 | } |
113 | | |
114 | | private: |
115 | | const ComponentDescriptor *Desc = nullptr; |
116 | | |
117 | | constexpr explicit PluginComponent(const ComponentDescriptor *D) noexcept |
118 | 0 | : Desc(D) {} |
119 | | friend class Plugin; |
120 | | }; |
121 | | |
122 | | class Plugin { |
123 | | public: |
124 | | struct VersionData { |
125 | | uint32_t Major; |
126 | | uint32_t Minor; |
127 | | uint32_t Patch; |
128 | | uint32_t Build; |
129 | | }; |
130 | | struct PluginDescriptor { |
131 | | const char *Name; |
132 | | const char *Description; |
133 | | uint32_t APIVersion; |
134 | | VersionData Version; |
135 | | size_t ModuleCount; |
136 | | PluginModule::ModuleDescriptor *ModuleDescriptions; |
137 | | size_t ComponentCount = 0; |
138 | | PluginComponent::ComponentDescriptor *ComponentDescriptions = nullptr; |
139 | | void (*AddOptions)(const PluginDescriptor *D, |
140 | | PO::ArgumentParser &Parser) noexcept; |
141 | | }; |
142 | | |
143 | | // Const value of current plugin API version. |
144 | | static inline constexpr const uint32_t CurrentAPIVersion [[maybe_unused]] = |
145 | | kPluginCurrentAPIVersion; |
146 | | |
147 | | // Static function to load plugins from default paths. |
148 | | WASMEDGE_EXPORT static void loadFromDefaultPaths() noexcept; |
149 | | |
150 | | // Static function to get default plugin paths. |
151 | | static std::vector<std::filesystem::path> getDefaultPluginPaths() noexcept; |
152 | | |
153 | | // Static function to load all plugins from given path. |
154 | | WASMEDGE_EXPORT static bool load(const std::filesystem::path &Path) noexcept; |
155 | | |
156 | | // Static function to register plugin with descriptor. |
157 | | static bool registerPlugin(const PluginDescriptor *Desc) noexcept; |
158 | | |
159 | | // Static function to add plugin options from arguments. |
160 | | static void addPluginOptions(PO::ArgumentParser &Parser) noexcept; |
161 | | |
162 | | // Static function to find loaded plugin by name. |
163 | | WASMEDGE_EXPORT static const Plugin *find(std::string_view Name) noexcept; |
164 | | |
165 | | // Static function to list loaded plugins. |
166 | | static const std::deque<Plugin> &plugins() noexcept; |
167 | | |
168 | | Plugin(const Plugin &) = delete; |
169 | | Plugin &operator=(const Plugin &) = delete; |
170 | | Plugin(Plugin &&) noexcept = default; |
171 | | Plugin &operator=(Plugin &&) noexcept = default; |
172 | | |
173 | | Plugin() noexcept = default; |
174 | | explicit Plugin(const PluginDescriptor *D) noexcept; |
175 | | |
176 | 0 | constexpr const char *name() const noexcept { |
177 | 0 | assuming(Desc); |
178 | 0 | return Desc->Name; |
179 | 0 | } |
180 | | |
181 | 0 | constexpr const char *description() const noexcept { |
182 | 0 | assuming(Desc); |
183 | 0 | return Desc->Description; |
184 | 0 | } |
185 | | |
186 | 0 | constexpr VersionData version() const noexcept { |
187 | 0 | assuming(Desc); |
188 | 0 | return Desc->Version; |
189 | 0 | } |
190 | | |
191 | 0 | void registerOptions(PO::ArgumentParser &Parser) const noexcept { |
192 | 0 | assuming(Desc); |
193 | 0 | if (Desc->AddOptions) { |
194 | 0 | Desc->AddOptions(Desc, Parser); |
195 | 0 | } |
196 | 0 | } |
197 | | |
198 | 0 | Span<const PluginModule> modules() const noexcept { |
199 | 0 | assuming(Desc); |
200 | 0 | return ModuleRegistry; |
201 | 0 | } |
202 | 0 | Span<const PluginComponent> components() const noexcept { |
203 | 0 | assuming(Desc); |
204 | 0 | return ComponentRegistry; |
205 | 0 | } |
206 | | |
207 | | WASMEDGE_EXPORT const PluginModule * |
208 | | findModule(std::string_view Name) const noexcept; |
209 | | |
210 | | WASMEDGE_EXPORT const PluginComponent * |
211 | | findComponent(std::string_view Name) const noexcept; |
212 | | |
213 | 0 | std::filesystem::path path() const noexcept { return Path; } |
214 | | |
215 | | private: |
216 | | // Guards PluginRegistry / PluginNameLookup. |
217 | | static std::shared_mutex Mutex; |
218 | | // std::deque (not std::vector) so that pointers/references returned by find() |
219 | | // and plugins() remain valid even when more plugins are appended later. |
220 | | static std::deque<Plugin> PluginRegistry; |
221 | | static std::unordered_map<std::string_view, std::size_t, Hash::Hash> |
222 | | PluginNameLookup; |
223 | | |
224 | | // Static function to load plugin from file. Thread-safe. Idempotent: a file |
225 | | // that has already been loaded in this process is skipped (not re-dlopen'd). |
226 | | static bool loadFile(const std::filesystem::path &Path) noexcept; |
227 | | |
228 | | // Static function to register built-in plugins. Thread-safe. |
229 | | static void registerBuiltInPlugins() noexcept; |
230 | | |
231 | | // Plugin contents. |
232 | | std::filesystem::path Path; |
233 | | const PluginDescriptor *Desc = nullptr; |
234 | | std::shared_ptr<Loader::SharedLibrary> Lib; |
235 | | std::vector<PluginModule> ModuleRegistry; |
236 | | std::vector<PluginComponent> ComponentRegistry; |
237 | | std::unordered_map<std::string_view, std::size_t, Hash::Hash> |
238 | | ModuleNameLookup; |
239 | | std::unordered_map<std::string_view, std::size_t, Hash::Hash> |
240 | | ComponentNameLookup; |
241 | | }; |
242 | | |
243 | | } // namespace Plugin |
244 | | } // namespace WasmEdge |