event_base_new_with_config() and related methods

svn:r789
This commit is contained in:
Niels Provos 2008-05-08 05:56:20 +00:00
parent 3b2022ef3a
commit 3f56e364b7
5 changed files with 159 additions and 3 deletions

View File

@ -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.

View 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)

76
event.c
View File

@ -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)
{

View 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);
@ -110,6 +112,50 @@ const char *event_base_get_method(struct event_base *);
*/
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.

View 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");
}