commit f189b4849bc824bef9752afe3a3cfef55b721370 Author: Nathaniel McCallum npmccallum@redhat.com Date: Tue Aug 9 18:05:49 2011 -0400
[all] add type support
Modules can now specify which types of events they support. This also means that users can specify which types of events they will require and that libverto will return only an implementation that supports the required features. This also adds a function which will permit you to query the features supported after a context is already created.
src/verto-glib.c | 19 ++++++++++++++- src/verto-libev.c | 7 +++++- src/verto-libevent.c | 5 +++- src/verto-module.h | 4 ++- src/verto-tevent.c | 5 +++- src/verto.c | 61 +++++++++++++++++++++++++++++++++---------------- src/verto.h | 55 +++++++++++++++++++++++++++++++-------------- 7 files changed, 114 insertions(+), 42 deletions(-) --- diff --git a/src/verto-glib.c b/src/verto-glib.c index c330bcf..7eedc1a 100644 --- a/src/verto-glib.c +++ b/src/verto-glib.c @@ -27,6 +27,23 @@ #include <verto-glib.h> #include <verto-module.h>
+#if GLIB_MAJOR_VERSION >= 2 +#if GLIB_MINOR_VERSION >= 29 +#ifndef WIN32 /* Not supported on Windows */ +#define HAS_SIGNAL VERTO_EV_TYPE_SIGNAL +#endif +#endif /* GLIB_MINOR_VERSION >= 29 */ +#endif /* GLIB_MAJOR_VERSION >= 2 */ +#ifndef HAS_SIGNAL +#define HAS_SIGNAL 0 +#endif + +#define VERTO_GLIB_SUPPORTED_TYPES (VERTO_EV_TYPE_IO \ + | VERTO_EV_TYPE_TIMEOUT \ + | VERTO_EV_TYPE_IDLE \ + | HAS_SIGNAL \ + | VERTO_EV_TYPE_CHILD) + typedef struct { GMainContext *context; GMainLoop *loop; @@ -213,7 +230,7 @@ glib_ctx_del(void *lp, const verto_ev *ev, void *evpriv) g_free(evpriv); }
-VERTO_MODULE(glib, g_main_context_default); +VERTO_MODULE(glib, g_main_context_default, VERTO_GLIB_SUPPORTED_TYPES);
verto_ev_ctx * verto_new_glib() { diff --git a/src/verto-libev.c b/src/verto-libev.c index 11e3ec2..c661231 100644 --- a/src/verto-libev.c +++ b/src/verto-libev.c @@ -127,7 +127,12 @@ libev_ctx_del(void *ctx, const verto_ev *ev, void *evpriv) free(evpriv); }
-VERTO_MODULE(libev, ev_loop_new); +VERTO_MODULE(libev, ev_loop_new, + VERTO_EV_TYPE_IO | + VERTO_EV_TYPE_TIMEOUT | + VERTO_EV_TYPE_IDLE | + VERTO_EV_TYPE_SIGNAL | + VERTO_EV_TYPE_CHILD);
verto_ev_ctx * verto_new_libev() diff --git a/src/verto-libevent.c b/src/verto-libevent.c index 87603b6..15c344d 100644 --- a/src/verto-libevent.c +++ b/src/verto-libevent.c @@ -126,7 +126,10 @@ libevent_ctx_del(void *ctx, const verto_ev *ev, void *evpriv) event_free(evpriv); }
-VERTO_MODULE(libevent, event_base_init); +VERTO_MODULE(libevent, event_base_init, + VERTO_EV_TYPE_IO | + VERTO_EV_TYPE_TIMEOUT | + VERTO_EV_TYPE_SIGNAL);
verto_ev_ctx * verto_new_libevent() diff --git a/src/verto-module.h b/src/verto-module.h index fad9042..93f58a9 100644 --- a/src/verto-module.h +++ b/src/verto-module.h @@ -31,7 +31,7 @@
#define VERTO_MODULE_VERSION 1 #define VERTO_MODULE_TABLE verto_module_table -#define VERTO_MODULE(name, symb) \ +#define VERTO_MODULE(name, symb, types) \ static verto_ev_ctx_funcs name ## _funcs = { \ name ## _ctx_free, \ name ## _ctx_run, \ @@ -44,6 +44,7 @@ VERTO_MODULE_VERSION, \ # name, \ # symb, \ + types, \ verto_new_ ## name, \ verto_default_ ## name, \ }; @@ -54,6 +55,7 @@ typedef struct { unsigned int vers; const char *name; const char *symb; + verto_ev_type types; verto_ev_ctx_constructor new_ctx; verto_ev_ctx_constructor def_ctx; } verto_module; diff --git a/src/verto-tevent.c b/src/verto-tevent.c index 91e61f9..05029dd 100644 --- a/src/verto-tevent.c +++ b/src/verto-tevent.c @@ -120,7 +120,10 @@ tevent_ctx_del(void *priv, const verto_ev *ev, void *evpriv) talloc_free(evpriv); }
-VERTO_MODULE(tevent, g_main_context_default); +VERTO_MODULE(tevent, g_main_context_default, + VERTO_EV_TYPE_IO | + VERTO_EV_TYPE_TIMEOUT | + VERTO_EV_TYPE_SIGNAL);
verto_ev_ctx * verto_new_tevent() diff --git a/src/verto.c b/src/verto.c index 01c8fdc..3a64384 100644 --- a/src/verto.c +++ b/src/verto.c @@ -150,6 +150,7 @@ pdladdrmodname(void *addr, char **buf) { struct _verto_ev_ctx { void *dll; void *modpriv; + verto_ev_type types; verto_ev_ctx_funcs funcs; verto_ev *events; }; @@ -208,8 +209,8 @@ _asprintf(char **strp, const char *fmt, ...) { }
static int -do_load_file(const char *filename, int reqsym, pdlmtype *dll, - const verto_module **module) +do_load_file(const char *filename, int reqsym, verto_ev_type reqtypes, + pdlmtype *dll, const verto_module **module) { *dll = pdlopenl(filename); if (!*dll) { @@ -226,6 +227,10 @@ do_load_file(const char *filename, int reqsym, pdlmtype *dll, if ((*module)->symb && reqsym && !pdlsymlinked(NULL, (*module)->symb)) goto error;
+ /* Check to make sure that this module supports our required features */ + if (reqtypes != VERTO_EV_TYPE_NONE && ((*module)->types & reqtypes) != reqtypes) + goto error; + /* Re-open in execution mode */ *dll = pdlreopen(filename, *dll); if (!*dll) @@ -239,13 +244,14 @@ do_load_file(const char *filename, int reqsym, pdlmtype *dll, return 1;
error: - pdlclose(dll); + pdlclose(*dll); return 0; }
static int do_load_dir(const char *dirname, const char *prefix, const char *suffix, - int reqsym, pdlmtype *dll, const verto_module **module) + int reqsym, verto_ev_type reqtypes, pdlmtype *dll, + const verto_module **module) { *module = NULL; DIR *dir = opendir(dirname); @@ -268,7 +274,7 @@ do_load_dir(const char *dirname, const char *prefix, const char *suffix, if (_asprintf(&tmp, "%s/%s", dirname, ent->d_name) < 0) continue;
- int success = do_load_file(tmp, reqsym, dll, module); + int success = do_load_file(tmp, reqsym, reqtypes, dll, module); free(tmp); if (success) break; @@ -280,7 +286,8 @@ do_load_dir(const char *dirname, const char *prefix, const char *suffix, }
static int -load_module(const char *impl, pdlmtype *dll, const verto_module **module) +load_module(const char *impl, verto_ev_type reqtypes, pdlmtype *dll, + const verto_module **module) { int success = 0; char *prefix = NULL; @@ -305,19 +312,26 @@ load_module(const char *impl, pdlmtype *dll, const verto_module **module) if (impl) { /* Try to do a load by the path */ if (strchr(impl, '/')) - success = do_load_file(impl, 0, dll, module); + success = do_load_file(impl, 0, reqtypes, dll, module); if (!success) { /* Try to do a load by the name */ tmp = NULL; if (_asprintf(&tmp, "%s%s%s", prefix, impl, suffix) > 0) { - success = do_load_file(tmp, 0, dll, module); + success = do_load_file(tmp, 0, reqtypes, dll, module); free(tmp); } } } else { /* First, try the default implementation (aka 'the cache')*/ *dll = NULL; - if (!(success = (*module = defmodule) != NULL)) { + *module = NULL; + + if (defmodule != NULL + && (reqtypes == VERTO_EV_TYPE_NONE + || (defmodule->types & reqtypes) == reqtypes)) + *module = defmodule; + + if (!(success = *module != NULL)) { /* NULL was passed, so we will use the dirname of * the prefix to try and find any possible plugins */ tmp = strdup(prefix); @@ -331,17 +345,17 @@ load_module(const char *impl, pdlmtype *dll, const verto_module **module)
if (dname && prefix) { /* Attempt to find a module we are already linked to */ - success = do_load_dir(dname, prefix, suffix, 1, dll, - module); + success = do_load_dir(dname, prefix, suffix, 1, reqtypes, + dll, module); if (!success) { #ifdef DEFAULT_LIBRARY /* Attempt to find the default module */ - success = load_module(DEFAULT_LIBRARY, dll, module); + success = load_module(DEFAULT_LIBRARY, reqtypes, dll, module); if (!success) #endif /* DEFAULT_LIBRARY */ /* Attempt to load any plugin (we're desperate) */ - success = do_load_dir(dname, prefix, suffix, 0, dll, - module); + success = do_load_dir(dname, prefix, suffix, 0, + reqtypes, dll, module); } }
@@ -406,13 +420,13 @@ signal_ignore(verto_ev_ctx *ctx, verto_ev *ev) }
verto_ev_ctx * -verto_new(const char *impl) +verto_new(const char *impl, verto_ev_type reqtypes) { pdlmtype dll = NULL; const verto_module *module = NULL; verto_ev_ctx *ctx = NULL;
- if (!load_module(impl, &dll, &module)) + if (!load_module(impl, reqtypes, &dll, &module)) return NULL;
ctx = module->new_ctx(); @@ -425,13 +439,13 @@ verto_new(const char *impl) }
verto_ev_ctx * -verto_default(const char *impl) +verto_default(const char *impl, verto_ev_type reqtypes) { pdlmtype dll = NULL; const verto_module *module = NULL; verto_ev_ctx *ctx = NULL;
- if (!load_module(impl, &dll, &module)) + if (!load_module(impl, reqtypes, &dll, &module)) return NULL;
ctx = module->def_ctx(); @@ -444,10 +458,10 @@ verto_default(const char *impl) }
int -verto_set_default(const char *impl) +verto_set_default(const char *impl, verto_ev_type reqtypes) { pdlmtype dll = NULL; /* we will leak the dll */ - return (!defmodule && impl && load_module(impl, &dll, &defmodule)); + return (!defmodule && impl && load_module(impl, reqtypes, &dll, &defmodule)); }
void @@ -671,6 +685,12 @@ verto_del(verto_ev *ev) free(ev); }
+verto_ev_type +verto_get_supported_types(verto_ev_ctx *ctx) +{ + return ctx->types; +} + /*** THE FOLLOWING ARE FOR IMPLEMENTATION MODULES ONLY ***/
verto_ev_ctx * @@ -689,6 +709,7 @@ verto_convert_funcs(const verto_ev_ctx_funcs *funcs,
ctx->modpriv = ctx_private; ctx->funcs = *funcs; + ctx->types = module->types;
if (!defmodule) defmodule = module; diff --git a/src/verto.h b/src/verto.h index b471044..557fcd7 100644 --- a/src/verto.h +++ b/src/verto.h @@ -43,11 +43,12 @@ typedef struct _verto_ev_ctx verto_ev_ctx; typedef struct _verto_ev verto_ev;
typedef enum { - VERTO_EV_TYPE_IO, - VERTO_EV_TYPE_TIMEOUT, - VERTO_EV_TYPE_IDLE, - VERTO_EV_TYPE_SIGNAL, - VERTO_EV_TYPE_CHILD + VERTO_EV_TYPE_NONE = 0, + VERTO_EV_TYPE_IO = 1, + VERTO_EV_TYPE_TIMEOUT = 1 << 1, + VERTO_EV_TYPE_IDLE = 1 << 2, + VERTO_EV_TYPE_SIGNAL = 1 << 3, + VERTO_EV_TYPE_CHILD = 1 << 4 } verto_ev_type;
typedef enum { @@ -64,7 +65,8 @@ typedef enum { typedef void (verto_callback)(verto_ev_ctx *ctx, verto_ev *ev);
/** - * Creates a new event context using an optionally specified implementation. + * Creates a new event context using an optionally specified implementation + * and/or optionally specified required features. * * If you are an application that has already decided on using a particular * event loop implementation, you should not call this function, but instead @@ -78,12 +80,13 @@ typedef void (verto_callback)(verto_ev_ctx *ctx, verto_ev *ev); * where you have a need to choose an implementation at run time, usually * for testing purposes. The second and more common is when you simply * wish to remain implementation agnostic. In this later case, you should - * always call like this: verto_new(NULL). This lets verto choose the best + * always call like this: verto_new(NULL, ...). This lets verto choose the best * implementation to use. * * If impl is not NULL, a new context is returned which is backed by the * implementation specified. If the implementation specified is not - * available, NULL is returned. The parameter 'impl' can specify: + * available or if the required types (reqtypes) are not provided by the + * named implementation, NULL is returned. The parameter 'impl' can specify: * * The full path to an implementation library * * The name of the implementation library (i.e. - "glib" or "libev") * @@ -107,12 +110,18 @@ typedef void (verto_callback)(verto_ev_ctx *ctx, verto_ev *ev); * Last, verto will attempt to load any implementation installed. The specific * order of this step is undefined. * + * In all cases above, if the implementation does not support all the specified + * features (reqtypes), it will be skipped and processing will continue from + * where it left off. This means that if verto_new() returns non-NULL it is + * guaranteed to support the features you specified. + * * @see verto_set_default() * @param impl The implementation to use, or NULL. + * @param reqtypes A bitwise or'd list of required event type features. * @return A new _ev_ctx, or NULL on error. Call verto_free() when done. */ verto_ev_ctx * -verto_new(const char *impl); +verto_new(const char *impl, verto_ev_type reqtypes);
/** * Gets the default event context using an optionally specified implementation. @@ -130,10 +139,11 @@ verto_new(const char *impl); * @see verto_new() * @see verto_free() * @param impl The implementation to use, or NULL. + * @param reqtypes A bitwise or'd list of required event type features. * @return The default _ev_ctx, or NULL on error. Call verto_free() when done. */ verto_ev_ctx * -verto_default(const char *impl); +verto_default(const char *impl, verto_ev_type reqtypes);
/** * Sets the default implementation to use by its name. @@ -142,20 +152,22 @@ verto_default(const char *impl); * following reasons: * 1. The default implementation was already set via verto_set_default(). * 2. The implementation specified could not be found. - * 3. The impl argument was NULL. - * 4. verto_new() was already called. - * 5. verto_default() was already called. - * 6. verto_new_NAME() was already called. - * 7. verto_default_NAME() was already called. - * 8. verto_convert_NAME() was already called. + * 3. The implementation specified didn't support the features specified. + * 4. The impl argument was NULL. + * 5. verto_new() was already called. + * 6. verto_default() was already called. + * 7. verto_new_NAME() was already called. + * 8. verto_default_NAME() was already called. + * 9. verto_convert_NAME() was already called. * * @see verto_new() * @see verto_default() * @param impl The implementation to use. + * @param reqtypes A bitwise or'd list of required event type features. * @return The default _ev_ctx, or NULL on error. Call verto_free() when done. */ int -verto_set_default(const char *impl); +verto_set_default(const char *impl, verto_ev_type reqtypes);
/** * Frees a verto_ev_ctx. @@ -430,4 +442,13 @@ verto_get_proc_status(const verto_ev *ev); void verto_del(verto_ev *ev);
+/** + * Returns the event types supported by this implementation. + * + * @param ctx The verto_ev_ctx to query. + * @return The event types supported. + */ +verto_ev_type +verto_get_supported_types(verto_ev_ctx *ctx); + #endif /* VERTO_H_ */
libverto-commits@lists.fedorahosted.org