Add new functions to access backends by their features and to query the features of a backend.

svn:r842
This commit is contained in:
Nick Mathewson 2008-05-31 14:37:31 +00:00
parent 9515c8076e
commit 05965921ab
10 changed files with 94 additions and 15 deletions

View File

@ -104,6 +104,8 @@ Changes in current version:
o constify struct timeval * where possible o constify struct timeval * where possible
o make event_get_supported_methods obey environment variables o make event_get_supported_methods obey environment variables
o support for edge-triggered events on epoll and kqueue backends: patch from Valery Kholodkov o support for edge-triggered events on epoll and kqueue backends: patch from Valery Kholodkov
o support for selecting event backends by their features, and for querying the features of a backend.
o change failing behavior of event_base_new_with_config: if a config is provided and no backend is selected, return NULL instead of aborting.
Changes in 1.4.0: Changes in 1.4.0:

View File

@ -120,7 +120,8 @@ struct eventop win32ops = {
win32_del, win32_del,
win32_dispatch, win32_dispatch,
win32_dealloc, win32_dealloc,
0 0, /* doesn't need reinit */
0, /* No features supported. */
}; };
#define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET))) #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))

View File

@ -83,7 +83,8 @@ struct eventop devpollops = {
devpoll_del, devpoll_del,
devpoll_dispatch, devpoll_dispatch,
devpoll_dealloc, devpoll_dealloc,
1 /* need reinit */ 1, /* need reinit */
EV_FEATURE_FDS|EV_FEATURE_O1,
}; };
#define NEVENT 32000 #define NEVENT 32000

View File

@ -83,7 +83,8 @@ struct eventop epollops = {
epoll_del, epoll_del,
epoll_dispatch, epoll_dispatch,
epoll_dealloc, epoll_dealloc,
1 /* need reinit */ 1, /* need reinit */
EV_FEATURE_ET|EV_FEATURE_O1,
}; };
#ifdef HAVE_SETFD #ifdef HAVE_SETFD

View File

@ -55,6 +55,7 @@ struct eventop {
void (*dealloc)(struct event_base *, void *); void (*dealloc)(struct event_base *, void *);
/* set if we need to reinitialize the event base */ /* set if we need to reinitialize the event base */
int need_reinit; int need_reinit;
enum event_method_feature features;
}; };
struct event_base { struct event_base {
@ -103,6 +104,8 @@ struct event_config_entry {
struct event_config { struct event_config {
TAILQ_HEAD(event_configq, event_config_entry) entries; TAILQ_HEAD(event_configq, event_config_entry) entries;
enum event_method_feature require_features;
}; };
/* Internal use only: Functions that might be missing from <sys/queue.h> */ /* Internal use only: Functions that might be missing from <sys/queue.h> */

29
event.c
View File

@ -219,7 +219,12 @@ event_is_method_disabled(const char *name)
for (i = 8; environment[i] != '\0'; ++i) for (i = 8; environment[i] != '\0'; ++i)
environment[i] = toupper(environment[i]); environment[i] = toupper(environment[i]);
return (getenv(environment) != NULL); return (getenv(environment) != NULL);
}
enum event_method_feature
event_base_get_features(struct event_base *base)
{
return base->evsel->features;
} }
struct event_base * struct event_base *
@ -250,6 +255,9 @@ event_base_new_with_config(struct event_config *cfg)
if (event_config_is_avoided_method(cfg, if (event_config_is_avoided_method(cfg,
eventops[i]->name)) eventops[i]->name))
continue; continue;
if ((eventops[i]->features & cfg->require_features)
!= cfg->require_features)
continue;
} }
/* also obey the environment variables */ /* also obey the environment variables */
@ -261,8 +269,14 @@ event_base_new_with_config(struct event_config *cfg)
base->evbase = base->evsel->init(base); base->evbase = base->evsel->init(base);
} }
if (base->evbase == NULL) if (base->evbase == NULL) {
event_errx(1, "%s: no event mechanism available", __func__); if (cfg == NULL)
event_errx(1, "%s: no event mechanism available", __func__);
else {
event_base_free(base);
return NULL;
}
}
if (getenv("EVENT_SHOW_METHOD")) if (getenv("EVENT_SHOW_METHOD"))
event_msgx("libevent using: %s", base->evsel->name); event_msgx("libevent using: %s", base->evsel->name);
@ -410,6 +424,7 @@ event_config_new(void)
return (NULL); return (NULL);
TAILQ_INIT(&cfg->entries); TAILQ_INIT(&cfg->entries);
cfg->require_features = 0;
return (cfg); return (cfg);
} }
@ -450,6 +465,16 @@ event_config_avoid_method(struct event_config *cfg, const char *method)
return (0); return (0);
} }
int
event_config_require_features(struct event_config *cfg,
enum event_method_feature features)
{
if (!cfg)
return (-1);
cfg->require_features = features;
return (0);
}
int int
event_priority_init(int npriorities) event_priority_init(int npriorities)
{ {

View File

@ -100,6 +100,11 @@ int event_base_dispatch(struct event_base *);
*/ */
const char *event_base_get_method(struct event_base *); const char *event_base_get_method(struct event_base *);
/**
Return a bitmask of the features implemented by an event base.
*/
enum event_method_feature event_base_get_features(struct event_base *base);
/** /**
Gets all event notification mechanisms supported by libevent. Gets all event notification mechanisms supported by libevent.
@ -144,6 +149,43 @@ void event_config_free(struct event_config *cfg);
*/ */
int event_config_avoid_method(struct event_config *cfg, const char *method); int event_config_avoid_method(struct event_config *cfg, const char *method);
enum event_method_feature {
/* Require an event method that allows edge-triggered events with EV_ET. */
EV_FEATURE_ET = 0x01,
/* Require an event method where having one event triggered among
* many is [approximately] an O(1) operation. This excludes (for
* example) select and poll, which are approximately O(N) for N
* equal to the total number of possible events. */
EV_FEATURE_O1 = 0x02,
/* Require an event method that allows file descriptors as well as
* sockets. */
EV_FEATURE_FDS = 0x04,
} event_method_feature;
/**
Enters a required event method feature that the application demands.
Note that not every feature or combination of features is supported
on every platform. Code that requests features should be prepared
to handle the case where event_base_new_with_config() returns NULL, as in:
<pre>
event_config_require_features(cfg, EV_FEATURE_ET);
base = event_base_new_with_config(cfg);
if (base == NULL) {
// We can't get edge-triggered behavior here.
event_config_require_features(cfg, 0);
base = event_base_new_with_config(cfg);
}
</pre>
@param cfg the event configuration object
@param feature a bitfield of one or more event_method_feature values.
Replaces values from previous calls to this function.
@return 0 on success, -1 on failure.
*/
int event_config_require_features(struct event_config *cfg,
enum event_method_feature feature);
/** /**
Initialize the event API. Initialize the event API.
@ -152,7 +194,8 @@ int event_config_avoid_method(struct event_config *cfg, const char *method);
can currently be used to avoid certain event notification mechanisms. can currently be used to avoid certain event notification mechanisms.
@param cfg the event configuration object @param cfg the event configuration object
@return an initialized event_base that can be used to registering events. @return an initialized event_base that can be used to registering events,
or NULL if no event base can be created with the requested event_config.
@see event_base_new(), event_base_free(), event_init(), event_assign() @see event_base_new(), event_base_free(), event_init(), event_assign()
*/ */
struct event_base *event_base_new_with_config(struct event_config *cfg); struct event_base *event_base_new_with_config(struct event_config *cfg);

View File

@ -90,7 +90,8 @@ const struct eventop kqops = {
kq_del, kq_del,
kq_dispatch, kq_dispatch,
kq_dealloc, kq_dealloc,
1 /* need reinit */ 1 /* need reinit */,
EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_FDS,
}; };
static void * static void *

3
poll.c
View File

@ -79,7 +79,8 @@ const struct eventop pollops = {
poll_del, poll_del,
poll_dispatch, poll_dispatch,
poll_dealloc, poll_dealloc,
0 0, /* doesn't need_reinit */
EV_FEATURE_FDS,
}; };
static void * static void *

View File

@ -84,7 +84,8 @@ const struct eventop selectops = {
select_del, select_del,
select_dispatch, select_dispatch,
select_dealloc, select_dealloc,
0 0, /* doesn't need reinit. */
EV_FEATURE_FDS,
}; };
static int select_resize(struct selectop *sop, int fdsz); static int select_resize(struct selectop *sop, int fdsz);