[dovecot-cvs] dovecot/src/lib Makefile.am, 1.71, 1.72 module-context.h, NONE, 1.1

tss at dovecot.org tss at dovecot.org
Thu Mar 29 14:51:35 EEST 2007


Update of /var/lib/cvs/dovecot/src/lib
In directory talvi:/tmp/cvs-serv16171/lib

Modified Files:
	Makefile.am 
Added Files:
	module-context.h 
Log Message:
Better type safety to module_contexts arrays. Already fixed some bugs.



Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib/Makefile.am,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -d -r1.71 -r1.72
--- Makefile.am	18 Mar 2007 01:57:11 -0000	1.71
+++ Makefile.am	29 Mar 2007 11:51:32 -0000	1.72
@@ -135,6 +135,7 @@
 	mempool.h \
 	mkdir-parents.h \
 	mmap-util.h \
+	module-context.h \
 	module-dir.h \
 	mountpoint.h \
 	network.h \

--- NEW FILE: module-context.h ---
#ifndef __MODULE_CONTEXT_H
#define __MODULE_CONTEXT_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_DEFINE(module_contexts, union STRUCT_NAME_module_context *);
   };
   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) \
	(*((void **)array_idx_modifiable(&(obj)->module_contexts, \
					(id_ctx).id.module_id) + \
	 OBJ_REGISTER_COMPATIBLE(obj, id_ctx)))

#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 *_module_tmp = ctx + \
		COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(module_ctx, \
			(**(obj)->module_contexts.v)) + \
		OBJ_REGISTER_COMPATIBLE(obj, id_ctx); \
	array_idx_set(&(obj)->module_contexts, \
		module_get_context_id(&(id_ctx).id), (void *)&_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



More information about the dovecot-cvs mailing list