gfactory
Loading...
Searching...
No Matches
gfactory.h
Go to the documentation of this file.
1#pragma once
15// C++
16#include <memory>
17#include <string>
18#include <string_view>
19#include <unordered_map>
20
21// gfactory
22#include "gdl.h"
23#include "gbase.h"
24#include "gfactory_options.h"
25
38{
39public:
41 virtual ~GFactoryBase() = default;
42
50 [[nodiscard]] virtual void* Create() = 0;
51};
52
64template <class T>
65class GFactory final : public GFactoryBase
66{
67public:
75 explicit GFactory(const std::shared_ptr<GOptions>& gopts)
76 : gopts_(gopts) {
77 static_assert(std::is_constructible_v<T, const std::shared_ptr<GOptions>&>,
78 "T must be constructible from const std::shared_ptr<GOptions>&");
79 }
80
85 [[nodiscard]] void* Create() override { return static_cast<void*>(new T(gopts_)); }
86
87private:
89 std::shared_ptr<GOptions> gopts_;
90};
91
121class GManager : public GBase<GManager>
122{
123public:
131 explicit GManager(const std::shared_ptr<GOptions>& gopt) : GBase(gopt, PLUGIN_LOGGER) {
132 }
133
135 GManager(const GManager&) = delete;
136 GManager& operator=(const GManager&) = delete;
137
139 GManager(GManager&&) noexcept = default;
140 GManager& operator=(GManager&&) noexcept = default;
141
147 ~GManager() override { clearDLMap(); }
148
158 template <class Derived>
159 void RegisterObjectFactory(std::string_view name);
160
168 template <class Derived>
169 void RegisterObjectFactory(std::string_view name, const std::shared_ptr<GOptions>& gopts);
170
181 template <class Base>
182 [[nodiscard]] Base* CreateObject(std::string_view name) const;
183
196 template <class T>
197 [[nodiscard]] std::shared_ptr<T> LoadAndRegisterObjectFromLibrary(std::string_view name,
198 const std::shared_ptr<GOptions>& gopts);
199
205 void clearDLMap() noexcept;
206
207private:
213 void registerDL(std::string_view name);
214
216 std::unordered_map<std::string, std::unique_ptr<GFactoryBase>> factoryMap_;
217
219 std::unordered_map<std::string, std::shared_ptr<DynamicLib>> dlMap_;
220
222 std::string gname;
223};
224
225
226inline void GManager::clearDLMap() noexcept {
227 // Clearing the map releases std::shared_ptr<DynamicLib> instances.
228 // Each DynamicLib destructor closes its dlopen handle.
229 dlMap_.clear();
230}
231
232inline void GManager::registerDL(std::string_view name) {
233 // Convention: plugins are packaged as "<name>.gplugin".
234 const std::string filename = std::string{name} + ".gplugin";
235
236 // Store the DynamicLib in a shared_ptr so it can be safely captured by
237 // a shared_ptr deleter in LoadAndRegisterObjectFromLibrary().
238 dlMap_.emplace(std::string{name},
239 std::make_shared<DynamicLib>(log, filename));
240 log->debug(NORMAL, "Loading DL ", name);
241}
242
243template <class Derived>
244void GManager::RegisterObjectFactory(std::string_view name) {
245 // Note: the factory is stored type-erased (GFactoryBase) but remains responsible for creating Derived.
246 factoryMap_.emplace(std::string{name}, std::make_unique<GFactory<Derived>>());
247 log->debug(NORMAL, "Registering ", name, " into factory map");
248}
249
250template <class Derived>
251void GManager::RegisterObjectFactory(std::string_view name, const std::shared_ptr<GOptions>& gopts) {
252 factoryMap_.emplace(std::string{name}, std::make_unique<GFactory<Derived>>(gopts));
253 log->debug(NORMAL, "Registering ", name, " into factory map");
254}
255
256template <class Base>
257Base* GManager::CreateObject(std::string_view name) const {
258 auto it = factoryMap_.find(std::string{name});
259 if (it == factoryMap_.end()) {
261 "Couldn't find factory <", name, "> in factory map.");
262 }
263 log->debug(NORMAL, "Creating instance of <", name, "> factory.");
264
265 // Type-erased creation returns void*; caller requests a Base* view.
266 return static_cast<Base*>(it->second->Create());
267}
268
269template <class T>
270std::shared_ptr<T> GManager::LoadAndRegisterObjectFromLibrary(std::string_view name,
271 const std::shared_ptr<GOptions>& gopts) {
272 registerDL(name);
273 auto pluginName = std::string{name};
274 auto pluginLib = dlMap_.at(pluginName); // shared_ptr<DynamicLib>
275
276 if (pluginLib && pluginLib->handle) {
277 // The product type performs the symbol lookup and raw allocation.
278 T* raw = T::instantiate(pluginLib->handle, gopts);
279
280 // Standardize logger wiring on the instance.
281 raw->set_loggers(gopts);
282
283 // Return shared_ptr<T> with a deleter that captures pluginLib so the library stays loaded
284 // until the object is destroyed.
285 return std::shared_ptr<T>(raw, [pluginLib](T* ptr) {
286 delete ptr;
287 // pluginLib keeps the dlopen handle alive until ptr is destroyed.
288 });
289 }
290
291 log->error(ERR_DLHANDLENOTFOUND, "Plugin ", name, " could not be loaded.");
292}
std::shared_ptr< GLogger > log
Type-erased factory interface used by GManager.
Definition gfactory.h:38
virtual void * Create()=0
Instantiate the concrete product.
virtual ~GFactoryBase()=default
Virtual destructor for safe deletion through base pointer.
Concrete factory that creates objects of type T.
Definition gfactory.h:66
GFactory(const std::shared_ptr< GOptions > &gopts)
Construct a factory bound to a specific configuration/options instance.
Definition gfactory.h:75
void * Create() override
Allocate a new instance of T.
Definition gfactory.h:85
void debug(debug_type type, Args &&... args) const
void error(int exit_code, Args &&... args) const
Factory registry and dynamic-library manager for run-time creation of plugin objects.
Definition gfactory.h:122
GManager(const std::shared_ptr< GOptions > &gopt)
Construct a manager instance.
Definition gfactory.h:131
GManager(GManager &&) noexcept=default
Allow move for container support.
std::shared_ptr< T > LoadAndRegisterObjectFromLibrary(std::string_view name, const std::shared_ptr< GOptions > &gopts)
Load a plugin library and instantiate an object from it.
Definition gfactory.h:270
GManager(const GManager &)=delete
No copy – the manager owns unique resources (factory objects and loaded libraries).
Base * CreateObject(std::string_view name) const
Create an instance of a previously registered factory.
Definition gfactory.h:257
GManager & operator=(const GManager &)=delete
void clearDLMap() noexcept
Release all loaded dynamic libraries.
Definition gfactory.h:226
void RegisterObjectFactory(std::string_view name)
Register a concrete factory under a string key.
Definition gfactory.h:244
#define ERR_FACTORYNOTFOUND
Definition gdl.h:26
#define ERR_DLHANDLENOTFOUND
Definition gdl.h:27
constexpr const char * PLUGIN_LOGGER
Logger channel used by the gfactory module and plugins loaded through it.
NORMAL
Helper that loads a shared library and holds its POSIX handle.
Definition gdl.h:51