1
#ifndef MODULE_CONTEXT_H
2
#define MODULE_CONTEXT_H
5
This is a bit complex to use, but it prevents using wrong module IDs
6
in module_contexts arrays.
9
The main structure is implemented like this:
11
struct STRUCT_NAME_module_register {
14
union STRUCT_NAME_module_context {
15
struct STRUCT_NAME_module_register *reg;
16
// it's allowed to have some structure here so it won't waste space.
17
// for example: struct STRUCT_NAME_vfuncs super;
20
ARRAY_DEFINE(module_contexts, union STRUCT_NAME_module_context *);
22
extern struct STRUCT_NAME_module_register STRUCT_NAME_module_register;
25
The usage in modules goes like:
27
static MODULE_CONTEXT_DEFINE(mymodule_STRUCT_NAME_module,
28
&STRUCT_NAME_module_register);
29
struct mymodule_STRUCT_NAME {
30
union STRUCT_NAME_module_context module_ctx;
31
// module-specific data
34
struct mymodule_STRUCT_NAME *ctx = i_new(...);
35
MODULE_CONTEXT_SET(obj, mymodule_STRUCT_NAME_module, ctx);
37
struct mymodule_STRUCT_NAME *ctx =
38
MODULE_CONTEXT(obj, mymodule_STRUCT_NAME_module);
41
#define OBJ_REGISTER(obj) \
42
((**(obj)->module_contexts.v)->reg)
43
#define OBJ_REGISTER_COMPATIBLE(obj, id_ctx) \
44
COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(OBJ_REGISTER(obj), (id_ctx).reg)
46
#define MODULE_CONTEXT(obj, id_ctx) \
47
(*((void **)array_idx_modifiable(&(obj)->module_contexts, \
48
(id_ctx).id.module_id) + \
49
OBJ_REGISTER_COMPATIBLE(obj, id_ctx)))
52
# define MODULE_CONTEXT_DEFINE(_name, _reg) \
54
struct module_context_id id; \
57
# define MODULE_CONTEXT_INIT(_reg) \
58
{ { &(_reg)->id, 0, FALSE }, NULL }
60
# define MODULE_CONTEXT_DEFINE(_name, _reg) \
62
struct module_context_id id; \
64
# define MODULE_CONTEXT_INIT(_reg) \
65
{ { &(_reg)->id, 0, FALSE } }
68
#define MODULE_CONTEXT_DEFINE_INIT(_name, _reg) \
69
MODULE_CONTEXT_DEFINE(_name, _reg) = MODULE_CONTEXT_INIT(_reg)
71
struct module_context_id {
72
unsigned int *module_id_register;
73
unsigned int module_id;
77
static inline unsigned int module_get_context_id(struct module_context_id *id)
79
if (!id->module_id_set) {
80
id->module_id = *id->module_id_register;
81
id->module_id_set = TRUE;
82
*id->module_id_register += 1;
87
#define MODULE_CONTEXT_SET_FULL(obj, id_ctx, ctx, module_ctx) STMT_START { \
88
void *_module_tmp = ctx + \
89
COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(module_ctx, \
90
(**(obj)->module_contexts.v)) + \
91
OBJ_REGISTER_COMPATIBLE(obj, id_ctx); \
92
array_idx_set_i(&(obj)->module_contexts.arr, \
93
module_get_context_id(&(id_ctx).id), &_module_tmp); \
96
#define MODULE_CONTEXT_SET(obj, id_ctx, context) \
97
MODULE_CONTEXT_SET_FULL(obj, id_ctx, context, &(context)->module_ctx)
98
#define MODULE_CONTEXT_SET_SELF(obj, id_ctx, context) \
99
MODULE_CONTEXT_SET_FULL(obj, id_ctx, context, context)
101
#define MODULE_CONTEXT_UNSET(obj, id_ctx) \
102
array_idx_clear(&(obj)->module_contexts, (id_ctx).id.module_id)