module-context.h revision 398b08ea29e1851ad7f8772d0d79418b9ee25a34
e364bf323ef28133cdf28e6b31bad47999cdbe49Timo Sirainen#ifndef MODULE_CONTEXT_H
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define MODULE_CONTEXT_H
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "array.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen/*
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen This is a bit complex to use, but it prevents using wrong module IDs
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen in module_contexts arrays.
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ---------
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen The main structure is implemented like this:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct STRUCT_NAME_module_register {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int id;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen };
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen union STRUCT_NAME_module_context {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct STRUCT_NAME_module_register *reg;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen // it's allowed to have some structure here so it won't waste space.
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen // for example: struct STRUCT_NAME_vfuncs super;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen };
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct STRUCT_NAME {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ARRAY_DEFINE(module_contexts, union STRUCT_NAME_module_context *);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen };
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen extern struct STRUCT_NAME_module_register STRUCT_NAME_module_register;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ---------
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen The usage in modules goes like:
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen static MODULE_CONTEXT_DEFINE(mymodule_STRUCT_NAME_module,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen &STRUCT_NAME_module_register);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct mymodule_STRUCT_NAME {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen union STRUCT_NAME_module_context module_ctx;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen // module-specific data
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen };
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct mymodule_STRUCT_NAME *ctx = i_new(...);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MODULE_CONTEXT_SET(obj, mymodule_STRUCT_NAME_module, ctx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mymodule_STRUCT_NAME *ctx =
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MODULE_CONTEXT(obj, mymodule_STRUCT_NAME_module);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen*/
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define OBJ_REGISTER(obj) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ((**(obj)->module_contexts.v)->reg)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define OBJ_REGISTER_COMPATIBLE(obj, id_ctx) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(OBJ_REGISTER(obj), (id_ctx).reg)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define MODULE_CONTEXT(obj, id_ctx) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (*((void **)array_idx_modifiable(&(obj)->module_contexts, \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen module_get_context_id(&(id_ctx).id)) + \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen OBJ_REGISTER_COMPATIBLE(obj, id_ctx)))
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#ifdef HAVE_TYPEOF
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen# define MODULE_CONTEXT_DEFINE(_name, _reg) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct _name { \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct module_context_id id; \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen typeof(_reg) reg; \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } _name
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen# define MODULE_CONTEXT_INIT(_reg) \
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen { { &(_reg)->id, 0, FALSE }, NULL }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen#else
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen# define MODULE_CONTEXT_DEFINE(_name, _reg) \
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct _name { \
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct module_context_id id; \
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen } _name
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen# define MODULE_CONTEXT_INIT(_reg) \
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen { { &(_reg)->id, 0, FALSE } }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#endif
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define MODULE_CONTEXT_DEFINE_INIT(_name, _reg) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MODULE_CONTEXT_DEFINE(_name, _reg) = MODULE_CONTEXT_INIT(_reg)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct module_context_id {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int *module_id_register;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned int module_id;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen bool module_id_set;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen};
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic inline unsigned int module_get_context_id(struct module_context_id *id)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (!id->module_id_set) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen id->module_id = *id->module_id_register;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen id->module_id_set = TRUE;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen *id->module_id_register += 1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return id->module_id;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen#define MODULE_CONTEXT_SET_FULL(obj, id_ctx, ctx, module_ctx) STMT_START { \
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen void *_module_tmp = ctx + \
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(module_ctx, \
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen (**(obj)->module_contexts.v)) + \
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen OBJ_REGISTER_COMPATIBLE(obj, id_ctx); \
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen array_idx_set_i(&(obj)->module_contexts.arr, \
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen module_get_context_id(&(id_ctx).id), &_module_tmp); \
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen } STMT_END
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen#define MODULE_CONTEXT_SET(obj, id_ctx, context) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MODULE_CONTEXT_SET_FULL(obj, id_ctx, context, &(context)->module_ctx)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define MODULE_CONTEXT_SET_SELF(obj, id_ctx, context) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen MODULE_CONTEXT_SET_FULL(obj, id_ctx, context, context)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define MODULE_CONTEXT_UNSET(obj, id_ctx) \
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen array_idx_clear(&(obj)->module_contexts, (id_ctx).id.module_id)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#endif
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen