1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#ifndef MODULE_CONTEXT_H
#define MODULE_CONTEXT_H
#include "array.h"
/*
This is a bit complex to use, but it prevents using wrong module IDs
in module_contexts arrays.
---------
The main structure is implemented like this:
struct STRUCT_NAME_module_register {
unsigned int id;
};
union STRUCT_NAME_module_context {
struct STRUCT_NAME_module_register *reg;
// it's allowed to have some structure here so it won't waste space.
// for example: struct STRUCT_NAME_vfuncs super;
};
struct STRUCT_NAME {
ARRAY(union STRUCT_NAME_module_context *) module_contexts;
};
extern struct STRUCT_NAME_module_register STRUCT_NAME_module_register;
---------
The usage in modules goes like:
static MODULE_CONTEXT_DEFINE(mymodule_STRUCT_NAME_module,
&STRUCT_NAME_module_register);
struct mymodule_STRUCT_NAME {
union STRUCT_NAME_module_context module_ctx;
// module-specific data
};
struct mymodule_STRUCT_NAME *ctx = i_new(...);
MODULE_CONTEXT_SET(obj, mymodule_STRUCT_NAME_module, ctx);
struct mymodule_STRUCT_NAME *ctx =
MODULE_CONTEXT(obj, mymodule_STRUCT_NAME_module);
*/
#define OBJ_REGISTER(obj) \
((**(obj)->module_contexts.v)->reg)
#define OBJ_REGISTER_COMPATIBLE(obj, id_ctx) \
COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(OBJ_REGISTER(obj), (id_ctx).reg)
#define MODULE_CONTEXT(obj, id_ctx) \
(module_get_context_id(&(id_ctx).id) < array_count(&(obj)->module_contexts) ? \
(*((void **)array_idx_modifiable(&(obj)->module_contexts, \
module_get_context_id(&(id_ctx).id)) + \
OBJ_REGISTER_COMPATIBLE(obj, id_ctx))) : NULL)
/* Will crash if context is missing. This is mainly used to simplify code and
keep static analyzers happy. This syntax discards result of i_panic and
returns NULL instead to keep compilers happy. */
#define MODULE_CONTEXT_REQUIRE(obj, id_ctx) \
(module_get_context_id(&(id_ctx).id) < array_count(&(obj)->module_contexts) ? \
(*((void **)array_idx_modifiable(&(obj)->module_contexts, \
module_get_context_id(&(id_ctx).id)) + \
OBJ_REGISTER_COMPATIBLE(obj, id_ctx))) : (i_panic("Module context " #id_ctx " missing"), NULL))
#ifdef HAVE_TYPEOF
# define MODULE_CONTEXT_DEFINE(_name, _reg) \
struct _name { \
struct module_context_id id; \
typeof(_reg) reg; \
} _name
# define MODULE_CONTEXT_INIT(_reg) \
{ { &(_reg)->id, 0, FALSE }, NULL }
#else
# define MODULE_CONTEXT_DEFINE(_name, _reg) \
struct _name { \
struct module_context_id id; \
} _name
# define MODULE_CONTEXT_INIT(_reg) \
{ { &(_reg)->id, 0, FALSE } }
#endif
#define MODULE_CONTEXT_DEFINE_INIT(_name, _reg) \
MODULE_CONTEXT_DEFINE(_name, _reg) = MODULE_CONTEXT_INIT(_reg)
struct module_context_id {
unsigned int *module_id_register;
unsigned int module_id;
bool module_id_set;
};
static inline unsigned int module_get_context_id(struct module_context_id *id)
{
if (!id->module_id_set) {
id->module_id = *id->module_id_register;
id->module_id_set = TRUE;
*id->module_id_register += 1;
}
return id->module_id;
}
#define MODULE_CONTEXT_SET_FULL(obj, id_ctx, ctx, module_ctx) STMT_START { \
(void)COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(module_ctx, \
(**(obj)->module_contexts.v)); \
(void)OBJ_REGISTER_COMPATIBLE(obj, id_ctx); \
void *_module_tmp = ctx; \
array_idx_set_i(&(obj)->module_contexts.arr, \
module_get_context_id(&(id_ctx).id), &_module_tmp); \
} STMT_END
#define MODULE_CONTEXT_SET(obj, id_ctx, context) \
MODULE_CONTEXT_SET_FULL(obj, id_ctx, context, &(context)->module_ctx)
#define MODULE_CONTEXT_SET_SELF(obj, id_ctx, context) \
MODULE_CONTEXT_SET_FULL(obj, id_ctx, context, context)
#define MODULE_CONTEXT_UNSET(obj, id_ctx) \
array_idx_clear(&(obj)->module_contexts, (id_ctx).id.module_id)
#endif
|