]> granicus.if.org Git - libevent/commitdiff
event_base_new_with_config() and related methods
authorNiels Provos <provos@gmail.com>
Thu, 8 May 2008 05:56:20 +0000 (05:56 +0000)
committerNiels Provos <provos@gmail.com>
Thu, 8 May 2008 05:56:20 +0000 (05:56 +0000)
svn:r789

ChangeLog
event-internal.h
event.c
include/event2/event.h
test/regress.c

index bca7bf80be9a8ea8e58fe08f9cac41cd627276bf..7e827109e4cf6a030c59a65423dfe9e0188669d3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -92,6 +92,7 @@ Changes in current version:
  o turn event_initialized() into a function, and add function equivalents to EVENT_SIGNAL and EVENT_FD so that people don't need to include event_struct.h
  o Build test directory correctly with CPPFLAGS set.
  o Provide an API for retrieving the supported event mechanisms.
+ o event_base_new_with_config() and corresponding config APIs.
 
 Changes in 1.4.0:
  o allow \r or \n individually to separate HTTP headers instead of the standard "\r\n"; from Charles Kerr.
index 10fd5d5b793f0be4556d56ba74418e931af678f4..97246ca151cc8d6c25d5b2b800edc38b7dc2e754 100644 (file)
@@ -95,6 +95,16 @@ struct event_base {
        struct event th_notify;
 };
 
+struct event_config_entry {
+       TAILQ_ENTRY(event_config_entry) (next);
+
+       const char *avoid_method;
+};
+
+struct event_config {
+       TAILQ_HEAD(event_configq, event_config_entry) entries;
+};
+
 /* Internal use only: Functions that might be missing from <sys/queue.h> */
 #ifndef HAVE_TAILQFOREACH
 #define        TAILQ_FIRST(head)               ((head)->tqh_first)
diff --git a/event.c b/event.c
index 11c91864058f71e0d58a0d7b891afd3e35ca1297..2f5ffa930eb97575c2b29d567eaf6f60bfb3662c 100644 (file)
--- a/event.c
+++ b/event.c
@@ -187,6 +187,26 @@ event_init(void)
 
 struct event_base *
 event_base_new(void)
+{
+       return (event_base_new_with_config(NULL));
+}
+
+static int
+event_config_is_avoided_method(struct event_config *cfg, const char *method)
+{
+       struct event_config_entry *entry;
+
+       TAILQ_FOREACH(entry, &cfg->entries, next) {
+               if (entry->avoid_method != NULL &&
+                   strcmp(entry->avoid_method, method) == 0)
+                       return (1);
+       }
+
+       return (0);
+}
+
+struct event_base *
+event_base_new_with_config(struct event_config *cfg)
 {
        int i;
        struct event_base *base;
@@ -208,6 +228,13 @@ event_base_new(void)
        
        base->evbase = NULL;
        for (i = 0; eventops[i] && !base->evbase; i++) {
+               if (cfg != NULL) {
+                       /* determine if this backend should be avoided */
+                       if (event_config_is_avoided_method(cfg,
+                               eventops[i]->name))
+                               continue;
+               }
+
                base->evsel = eventops[i];
 
                base->evbase = base->evsel->init(base);
@@ -348,6 +375,55 @@ event_supported_methods()
        return (methods);
 }
 
+struct event_config *
+event_config_new(void)
+{
+       struct event_config *cfg = mm_malloc(sizeof(*cfg));
+
+       if (cfg == NULL)
+               return (NULL);
+
+       TAILQ_INIT(&cfg->entries);
+       
+       return (cfg);
+}
+
+static void
+event_config_entry_free(struct event_config_entry *entry)
+{
+       if (entry->avoid_method != NULL)
+               mm_free((char *)entry->avoid_method);
+       mm_free(entry);
+}
+
+void
+event_config_free(struct event_config *cfg)
+{
+       struct event_config_entry *entry;
+
+       while ((entry = TAILQ_FIRST(&cfg->entries)) != NULL) {
+               TAILQ_REMOVE(&cfg->entries, entry, next);
+               event_config_entry_free(entry);
+       }
+}
+
+int
+event_config_avoid_method(struct event_config *cfg, const char *method)
+{
+       struct event_config_entry *entry = mm_malloc(sizeof(*entry));
+       if (entry == NULL)
+               return (-1);
+
+       if ((entry->avoid_method = mm_strdup(method)) == NULL) {
+               mm_free(entry);
+               return (-1);
+       }
+
+       TAILQ_INSERT_TAIL(&cfg->entries, entry, next);
+
+       return (0);
+}
+
 int
 event_priority_init(int npriorities)
 {
index 4ceede73e373dedcbfbb059d1b2b04745abeb775..8dff9a7c7ca8ac010d181ff3ab9c0ca28a50c574 100644 (file)
@@ -58,6 +58,7 @@ typedef unsigned short u_short;
 
 struct event_base;
 struct event;
+struct event_config;
 
 /**
   Initialize the event API.
@@ -66,7 +67,8 @@ struct event;
   the current_base global.   If using only event_base_new(), each event
   added must have an event base set with event_base_set()
 
-  @see event_base_set(), event_base_free(), event_init()
+  @see event_base_set(), event_base_free(), event_init(),
+    event_base_new_with_config()
  */
 struct event_base *event_base_new(void);
 
@@ -109,8 +111,52 @@ const char *event_base_get_method(struct event_base *);
      error is encountered NULL is returned.
 */
 const char **event_supported_methods(void);
-        
-        
+
+/**
+   Allocates a new event configuration object.
+
+   The event configuration object can be used to change the behavior of
+   an event base.
+
+   @return an event_config object that can be used to store configuration or
+     NULL when an error is encountered.
+*/
+
+struct event_config *event_config_new(void);
+
+/**
+   Deallocates all memory associated with an event configuration object
+
+   @param cfg the event configuration object to be freed.
+*/
+void event_config_free(struct event_config *cfg);
+
+/**
+   Enters an event method that should be avoided into the configuration.
+
+   This can be used to avoid event mechanisms that do not support certain
+   file descriptor types.  An application can make use of multiple event
+   bases to accomodate incompatible file descriptor types.
+
+   @param cfg the event configuration object
+   @param method the event method to avoid
+   @return 0 on success, -1 on failure.
+*/
+int event_config_avoid_method(struct event_config *cfg, const char *method);
+
+/**
+  Initialize the event API.
+
+  Use event_base_new_with_config() to initialize a new event base, taking
+  the specified configuration under consideration.  The configuration object
+  can currently be used to avoid certain event notification mechanisms.
+
+  @param cfg the event configuration object
+  @return an initialized event_base that can be used to registering events.
+  @see event_base_new(), event_base_free(), event_init(), event_assign()
+*/
+struct event_base *event_base_new_with_config(struct event_config *cfg);
+
 /**
   Deallocate all memory associated with an event_base, and free the base.
 
index b8c69f0ead91f6aa995b721f2dcc83625aea06a4..fa5202b003d18ac4e80d77424118e8fa0de6ebff 100644 (file)
@@ -2070,6 +2070,9 @@ static void
 test_methods(void)
 {
        const char **methods = event_supported_methods();
+       struct event_config *cfg;
+       struct event_base *base;
+       const char *backend;
 
        fprintf(stderr, "Testing supported methods: ");
 
@@ -2078,11 +2081,31 @@ test_methods(void)
                exit(1);
        }
 
+       backend = methods[0];
        while (*methods != NULL) {
                fprintf(stderr, "%s ", *methods);
                ++methods;
        }
 
+       cfg = event_config_new();
+       assert(cfg != NULL);
+
+       assert(event_config_avoid_method(cfg, backend) == 0);
+
+       base = event_base_new_with_config(cfg);
+       if (base == NULL) {
+               fprintf(stderr, "FAILED\n");
+               exit(1);
+       }
+
+       if (strcmp(backend, event_base_get_method(base)) == 0) {
+               fprintf(stderr, "FAILED\n");
+               exit(1);
+       }
+
+       event_base_free(base);
+       event_config_free(cfg);
+
        fprintf(stderr, "OK\n");
 }