libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_module.h
Go to the documentation of this file.
1/*! \file
2 * \brief Dynamic module and plugin system.
3 * \ingroup core
4 *
5 * This file contains the type declarations of GblModule
6 * and its associated API, providing the functionality of
7 * a static registry of lazily loaded "services" or C++
8 * singleton types and their associated type registry.
9 *
10 * \todo
11 * - advanced unit testing
12 * - plan out type registration/management
13 * - rig up option group parsery
14 * - stop inheriting GblContext
15 *
16 * \author 2023, 2025 Falco Girgis
17 * \copyright MIT License
18 */
19#ifndef GIMBAL_MODULE_H
20#define GIMBAL_MODULE_H
21
22#include "../meta/instances/gimbal_context.h"
23#include "../meta/ifaces/gimbal_iplugin.h"
24#include "../strings/gimbal_string_ref.h"
25#include "../utils/gimbal_version.h"
26#include "../utils/gimbal_option_group.h"
27
28/*! \name Type System
29 * \brief Type UUID and cast operators.
30 * @{
31 */
32#define GBL_MODULE_TYPE GBL_TYPEID(GblModule) //!< Type UUID for GblModule
33#define GBL_MODULE(self) GBL_CAST(GblModule, self) //!< Function-style GblInstance cast
34#define GBL_MODULE_CLASS(klass) GBL_CLASS_CAST(GblModule, klass) //!< Function-style GblClass cast
35#define GBL_MODULE_CLASSOF(self) GBL_CLASSOF(GblModule, self) //!< Gets a GblModuleClass from GblInstance
36//! @}
37
38/*! Macro directive for importing a module.
39
40 Used to "import" a GblModule whose type has been registered with the type system,
41 lazily loading it the fist time and returning references to it subsequently.
42
43 \code {.c}
44 MyModule* module = GBL_REQUIRE(MyModule, "1.0.1");
45 GBL_ASSERT(module, "Failed to load MyModule!");
46 \endcode
47
48 \param typename Struct name for desired GblModule instance structure.
49 \param version [optional] Major.minor.patch string for specific version.
50
51 \retval GblModule* An auto-casted pointer to the instance of the desire module.
52 \retval NULL The module wasn't present or the version was too low.
53*/
54#define GBL_REQUIRE(.../* typename (, version) */) GBL_REQUIRE_(__VA_ARGS__)
55
56#define GBL_SELF_TYPE GblModule
57
59
60GBL_FORWARD_DECLARE_STRUCT(GblOptionGroup);
62
63//! Function callback used with GblModule_foreach() for iterating over active modules, returning GBL_TRUE to end iteration early.
64typedef GblBool (*GblModuleIterFn)(GblModule* pIt, void* pClosure);
65
66/*! \struct GblModuleClass
67 * \extends GblContextClass
68 * \implements GblIPluginClass
69 * \brief GblClass structure for GblModule
70 *
71 * Virtual method table for GblModule
72 * - inherits from GblContext
73 * - has to implement GblIPlugin's VTable
74 * - adds pure virtaul methods load/unload
75 *
76 * \sa GblModule, GblIPluginClass
77 */
78GBL_CLASS_DERIVE(GblModule, GblContext, GblIPlugin)
79 GBL_RESULT (*pFnLoad) (GBL_SELF); //!< Called when a GblModule is first loaded
80 GBL_RESULT (*pFnUnload)(GBL_SELF); //!< Called after the GblModule is done being referenced
82
83/*! \struct GblModule
84 * \ingroup core
85 * \extends GblContext
86 * \implements GblIPlugin
87 * \brief Dynamically loadable service and associated meta types.
88 *
89 * A Module is a lazily-loaded object which is registered then later
90 * can be queried for by anywhere else in the application. This
91 * behavior lets you implement "services" as global singletons which
92 * can be accessed from anywhere. Modules also maintain their own inner
93 * registry of associated meta types, which is managed through the
94 * implemented GblIPlugin interface.
95 *
96 * \sa GbModuleClass, GblIPlugin
97 */
99 GblVersion version; //!< Version of a module
100 GblStringRef* pPrefix; //!< Namespace prefix of a module
101 GblStringRef* pAuthor; //!< Author(s) of a module
102 GblStringRef* pDescription; //!< Description of a module
103 GblOptionGroup* pOptionGroup; //!< Command-line option handler of a module
105
106//! \cond
107GBL_PROPERTIES(GblModule,
108 (prefix, GBL_GENERIC, (READ, WRITE, LOAD, SAVE), GBL_STRING_TYPE),
109 (version, GBL_GENERIC, (READ, WRITE, LOAD, SAVE), GBL_UINT32_TYPE),
110 (author, GBL_GENERIC, (READ, WRITE, LOAD, SAVE), GBL_STRING_TYPE),
111 (description, GBL_GENERIC, (READ, WRITE, LOAD, SAVE), GBL_STRING_TYPE),
112 (optionGroup, GBL_GENERIC, (READ, WRITE, LOAD, SAVE, IN), GBL_OPTION_GROUP_TYPE),
113 (useCount, GBL_GENERIC, (READ), GBL_INT16_TYPE)
114)
115
116GBL_SIGNALS(GblModule,
117 (loaded),
118 (unloaded)
119)
120//! \endcond
121
122//! Returns the GblType UUID associated with GblModule.
124
125/*! \name Registry
126 * \brief Static routines for querying the module registry.
127 * @{
128 */
129//! Returns a pointer to the module with the gibven name, if present, gracefully returning NULL otherwise.
130GBL_EXPORT GblModule* GblModule_find (const char* pName) GBL_NOEXCEPT;
131//! Equivalent to GblModule_find(), except doing a faster search using a GblQuark for the name.
133//! Returns a pointer to the GblModule which has been loaded at the given index, or NULL if there isn't one.
134GBL_EXPORT GblModule* GblModule_at (size_t index) GBL_NOEXCEPT;
135//! Returns the total number of modules which have been registered.
137//! Iterates over every registered module, invoking the provided iterator callback, optionally passing back an arbitrary userdata closure pointer.
138GBL_EXPORT GblBool GblModule_iterate (GblModuleIterFn pFnIter,
139 void* pCl/*=NULL*/) GBL_NOEXCEPT;
140//! @}
141
142/*! \name Importing
143 * \brief Routines for returning a module
144 * @{
145 */
146//! Loads or returns a module matching the given name and optional version identifier, raising an error and returning NULL if there was no match.
147GBL_EXPORT GblModule* GblModule_require (const char* pName,
148 const char* pVersion/*=NULL*/,
149 const char* pFile/*=__FILE__*/,
150 const char* pFunc/*=__func__*/,
151 size_t line/*=__LINE__*/) GBL_NOEXCEPT;
152//! Equivalent to GblModule_require(), except using a faster quark for the name identifier.
154 const char* pVersion/*=NULL*/,
155 const char* pFile/*=__FILE__*/,
156 const char* pFunc/*=__func__*/,
157 size_t line/*=__LINE__*/) GBL_NOEXCEPT;
158//! @}
159
160/*! \name Lifetime
161 * \brief Methods for creating and destroying modules.
162 * @{
163 */
164//! Creates and returns a reference to a new GblModule-compatible instance type, but does not add it to the registry.
165GBL_EXPORT GblModule* GblModule_create (GblType derivedType,
166 const char* pName,
167 GblVersion version,
168 const char* pAuthor,
169 const char* pDescription,
170 const char* pPrefix) GBL_NOEXCEPT;
171//! Releases a reference to a previously created GblModule instance, destructing and freeing it if there are no references left.
173//! @}
174
175/*! \name Registration
176 * \brief Methods for adding and removing from the registry.
177 * @{
178 */
179//! Attempts to register a previously instantiated GblModule instance as a globally importable module within the internal registry.
181//! Attempts to unregister a previously registered GblModule instance, removing it from the internal registry.
183//! @}
184
185/*! \name Loading/Unloading
186 * \brief Routines for controlling when a module is loaded and unloaded.
187 * @{
188 */
189//! Manually increments the given module's usage count, loading it on first usage. You can manually control its lifetimeto prevent being dynamically unloaded like this.
191//! Manually decrements the given module's usage count, unloading it when the last user is done. You can manually control unloading it like this.
193//! Retrieves the current usage counter for the given module.
195//! Returns true if the given module is currently loaded and has active uses, return false otherwise.
197//! @}
198
200
201// ====== IMPLEMENTATION =====
202///\cond
203#define GBL_REQUIRE_(...)
204 GBL_VA_OVERLOAD_CALL(GBL_REQUIRE_, GBL_VA_OVERLOAD_SUFFIXER_ARGC, __VA_ARGS__)
205
206#define GBL_REQUIRE__1(type)
207 GBL_CAST(type, GblModule_require(GblType_name(GBL_TYPEID(type)),
208 GBL_NULL, __FILE__, __func__,
209 __LINE__))
210#define GBL_REQUIRE__2(type, name)
211 GBL_CAST(type, GblModule_require(name, GBL_NULL, __FILE__, __func__,
212 __LINE__))
213
214#define GBL_REQUIRE__3(type, name, version)
215 GBL_CAST(type, GblModule_require(name, version, __FILE__, __func__,
216 __LINE__))
217
218#define GblModule_iterate(...)
219 GblModule_iterateDefault_(__VA_ARGS__)
220#define GblModule_iterateDefault_(...)
221 GblModule_iterateDefault__(__VA_ARGS__, NULL)
222#define GblModule_iterateDefault__(iter, cl, ...)
223 (GblModule_iterate)(iter, cl)
224
225///\endcond
226
227#undef GBL_SELF_TYPE
228
229#endif // GIMBAL_MODULE_H
#define GBL_NULL
#define GBL_NOEXCEPT
#define GBL_DECLS_BEGIN
#define GBL_FORWARD_DECLARE_STRUCT(S)
#define GBL_TYPEID(instanceStruct)
#define GBL_INSTANCE_DERIVE(derivedInstance, baseInstance)
#define GBL_CLASS_DERIVE(...)
#define GBL_INSTANCE_END
#define GBL_EXPORT
#define GBL_CLASS_END
#define GBL_VA_OVERLOAD_CALL(BASE, SUFFIXER,...)
#define GBL_VA_OVERLOAD_SUFFIXER_ARGC(...)
GBL_RESULT GblModule_unregister(GblModule *pSelf)
Attempts to unregister a previously registered GblModule instance, removing it from the internal regi...
GblModule * GblModule_at(size_t index)
Returns a pointer to the GblModule which has been loaded at the given index, or NULL if there isn't o...
size_t GblModule_count(void)
Returns the total number of modules which have been registered.
GBL_RESULT GblModule_unuse(GblModule *pSelf)
Manually decrements the given module's usage count, unloading it when the last user is done....
GblRefCount GblModule_unref(GblModule *pSelf)
Releases a reference to a previously created GblModule instance, destructing and freeing it if there ...
GblModule * GblModule_create(GblType derivedType, const char *pName, GblVersion version, const char *pAuthor, const char *pDescription, const char *pPrefix)
Creates and returns a reference to a new GblModule-compatible instance type, but does not add it to t...
GblModule * GblModule_requireQuark(GblQuark name, const char *pVersion, const char *pFile, const char *pFunc, size_t line)
Equivalent to GblModule_require(), except using a faster quark for the name identifier.
GblModule * GblModule_find(const char *pName)
Returns a pointer to the module with the gibven name, if present, gracefully returning NULL otherwise...
GblRefCount GblModule_useCount(const GblModule *pSelf)
Retrieves the current usage counter for the given module.
GblModule * GblModule_require(const char *pName, const char *pVersion, const char *pFile, const char *pFunc, size_t line)
Loads or returns a module matching the given name and optional version identifier,...
GblBool GblModule_isLoaded(const GblModule *pSelf)
Returns true if the given module is currently loaded and has active uses, return false otherwise.
GblModule * GblModule_findQuark(GblQuark name)
Equivalent to GblModule_find(), except doing a faster search using a GblQuark for the name.
GBL_RESULT GblModule_register(GblModule *pSelf)
Attempts to register a previously instantiated GblModule instance as a globally importable module wit...
GblBool GblModule_iterate(GblModuleIterFn pFnIter, void *pCl)
Iterates over every registered module, invoking the provided iterator callback, optionally passing ba...
GblType GblModule_type(void)
Returns the GblType UUID associated with GblModule.
GBL_RESULT GblModule_use(GblModule *pSelf)
Manually increments the given module's usage count, loading it on first usage. You can manually contr...
#define GBL_OPTION_GROUP_TYPE
Type UUID for GblOptionGroup.
#define GBL_INT16_TYPE
Builtin ID for int16_t GblVariant type.
#define GBL_STRING_TYPE
Builtin ID for string GblVariant type.
#define GBL_UINT32_TYPE
Builtin ID for uint32_t GblVariant type.
#define GBL_PROPERTIES(object,...)
Declares a list of properties for the given object/instance structure.
#define GBL_SIGNALS(instanceStruct,...)
Declares a list of signals to be associated with the given instanceStruct.
uint8_t GblBool
Basic boolean type, standardized to sizeof(char)
uint16_t GblRefCount
Type able to hold a reference counter across the codebase.
uintptr_t GblType
Meta Type UUID.
Definition gimbal_type.h:52
uintptr_t GblQuark
Uniquely identifiable interned string type.
const char GblStringRef
Reference-counted, const char*-compatible string type.
uint32_t GblVersion
32-bit unsigned integer representing a packed version in the form (MAJOR.MINOR.PATCH)
Dynamically loadable service and associated meta types.
GblStringRef * pDescription
Description of a module.
GblStringRef * pAuthor
Author(s) of a module.
GblStringRef * pPrefix
Namespace prefix of a module.
GblOptionGroup * pOptionGroup
Command-line option handler of a module.
GblVersion version
Version of a module.