mirror of
https://github.com/libevent/libevent.git
synced 2025-01-09 00:56:20 +08:00
rollback r594: restructuring to make event activation independent.
changes are going to wait for api design svn:r612
This commit is contained in:
parent
68725dc8bd
commit
03589ccb12
@ -25,7 +25,6 @@ Changes in current version:
|
||||
o pull setters/getters out of RPC structures into a base class to which we just need to store a pointer; this reduces the memory footprint of these structures.
|
||||
o prefix {encode,decode}_tag functions with evtag to avoid collisions
|
||||
o fix a bug with event_rpcgen for integers
|
||||
o restructure the code to make event activation independent of regular event logic
|
||||
o Correctly handle DNS replies with no answers set (Fixes bug 1846282)
|
||||
o add -Wstrict-aliasing to warnings and more cleanup
|
||||
o removed linger from http server socket; reported by Ilya Martynov
|
||||
|
@ -57,7 +57,7 @@ struct event_base {
|
||||
int event_break; /* Set to terminate loop immediately */
|
||||
|
||||
/* active event management */
|
||||
TAILQ_HEAD (eventhead_list, event_head) **activequeues;
|
||||
struct event_list **activequeues;
|
||||
int nactivequeues;
|
||||
|
||||
/* signal handling info */
|
||||
@ -69,9 +69,6 @@ struct event_base {
|
||||
struct min_heap timeheap;
|
||||
};
|
||||
|
||||
#define EVENT_CB(x) \
|
||||
(void (*)(struct event_base *, struct event_head *, int, void *))(x)
|
||||
|
||||
/* Internal use only: Functions that might be missing from <sys/queue.h> */
|
||||
#ifndef HAVE_TAILQFOREACH
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
|
202
event.c
202
event.c
@ -155,80 +155,6 @@ gettime(struct timeval *tp)
|
||||
return (gettimeofday(tp, NULL));
|
||||
}
|
||||
|
||||
/* glue stuff */
|
||||
|
||||
static int
|
||||
event_is_active(struct event_head *ev)
|
||||
{
|
||||
return (ev->ev_flags & EVLIST_ACTIVE);
|
||||
}
|
||||
|
||||
static int
|
||||
event_active_events(struct event_head *ev)
|
||||
{
|
||||
return (ev->ev_res);
|
||||
}
|
||||
|
||||
static void
|
||||
event_head_set(struct event_head *ev,
|
||||
void (*cb)(struct event_base *, struct event_head *, int, void *),
|
||||
void *cb_arg)
|
||||
{
|
||||
ev->ev_pri = 0;
|
||||
ev->ev_res = 0;
|
||||
ev->ev_flags = EVLIST_INIT;
|
||||
|
||||
ev->ev_cb = cb;
|
||||
ev->ev_cb_arg = cb_arg;
|
||||
}
|
||||
|
||||
static void
|
||||
event_make_active(struct event_base *base, struct event_head *ev, int events)
|
||||
{
|
||||
if (ev->ev_flags & EVLIST_ACTIVE) {
|
||||
ev->ev_res |= events;
|
||||
return;
|
||||
}
|
||||
|
||||
if (~ev->ev_flags & EVLIST_INTERNAL)
|
||||
base->event_count++;
|
||||
base->event_count_active++;
|
||||
|
||||
TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri], ev, ev_active_next);
|
||||
ev->ev_flags |= EVLIST_ACTIVE;
|
||||
ev->ev_res = events;
|
||||
}
|
||||
|
||||
static void
|
||||
event_remove_active(struct event_base *base, struct event_head *ev)
|
||||
{
|
||||
if (!(ev->ev_flags & EVLIST_ACTIVE))
|
||||
event_errx(1, "%s: %p not on active queue", __func__, ev);
|
||||
if (~ev->ev_flags & EVLIST_INTERNAL)
|
||||
base->event_count--;
|
||||
base->event_count_active--;
|
||||
|
||||
TAILQ_REMOVE(base->activequeues[ev->ev_pri], ev, ev_active_next);
|
||||
ev->ev_flags &= ~EVLIST_ACTIVE;
|
||||
}
|
||||
|
||||
static int
|
||||
event_head_priority_set(struct event_base *base,
|
||||
struct event_head *ev, int pri)
|
||||
{
|
||||
if (event_is_active(ev))
|
||||
return (-1);
|
||||
|
||||
if (pri < 0 || pri >= base->nactivequeues)
|
||||
return (-1);
|
||||
|
||||
ev->ev_pri = pri;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* back to normal stuff */
|
||||
|
||||
struct event_base *
|
||||
event_init(void)
|
||||
{
|
||||
@ -375,9 +301,9 @@ event_base_priority_init(struct event_base *base, int npriorities)
|
||||
|
||||
/* Allocate our priority queues */
|
||||
base->nactivequeues = npriorities;
|
||||
base->activequeues = (struct eventhead_list **)event_calloc(
|
||||
base->activequeues = (struct event_list **)event_calloc(
|
||||
base->nactivequeues,
|
||||
npriorities * sizeof(struct eventhead_list *));
|
||||
npriorities * sizeof(struct event_list *));
|
||||
if (base->activequeues == NULL)
|
||||
event_err(1, "%s: calloc", __func__);
|
||||
|
||||
@ -397,32 +323,6 @@ event_haveevents(struct event_base *base)
|
||||
return (base->event_count > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Traditional libevent events get deleted when they become active
|
||||
* unless they have specifically been set to be persistent.
|
||||
*/
|
||||
|
||||
static void
|
||||
event_legacy_handler(struct event_base *base, struct event *ev,
|
||||
int events, void *arg)
|
||||
{
|
||||
short ncalls;
|
||||
|
||||
if (!(ev->ev_events & EV_PERSIST))
|
||||
event_del(ev);
|
||||
|
||||
/* Allows deletes to work */
|
||||
ncalls = ev->ev_ncalls;
|
||||
ev->ev_pncalls = &ncalls;
|
||||
while (ncalls) {
|
||||
ncalls--;
|
||||
ev->ev_ncalls = ncalls;
|
||||
(*ev->ev_callback)((int)ev->ev_fd, events, ev->ev_arg);
|
||||
if (event_gotsig || base->event_break)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Active events are stored in priority queues. Lower priorities are always
|
||||
* process before higher priorities. Low priority events can starve high
|
||||
@ -432,9 +332,10 @@ event_legacy_handler(struct event_base *base, struct event *ev,
|
||||
static void
|
||||
event_process_active(struct event_base *base)
|
||||
{
|
||||
struct event_head *ev;
|
||||
struct eventhead_list *activeq = NULL;
|
||||
struct event *ev;
|
||||
struct event_list *activeq = NULL;
|
||||
int i;
|
||||
short ncalls;
|
||||
|
||||
for (i = 0; i < base->nactivequeues; ++i) {
|
||||
if (TAILQ_FIRST(base->activequeues[i]) != NULL) {
|
||||
@ -446,11 +347,21 @@ event_process_active(struct event_base *base)
|
||||
assert(activeq != NULL);
|
||||
|
||||
for (ev = TAILQ_FIRST(activeq); ev; ev = TAILQ_FIRST(activeq)) {
|
||||
event_remove_active(base, ev);
|
||||
if (ev->ev_events & EV_PERSIST)
|
||||
event_queue_remove(base, ev, EVLIST_ACTIVE);
|
||||
else
|
||||
event_del(ev);
|
||||
|
||||
(*ev->ev_cb)(base, ev, ev->ev_res, ev->ev_cb_arg);
|
||||
if (event_gotsig || base->event_break)
|
||||
return;
|
||||
/* Allows deletes to work */
|
||||
ncalls = ev->ev_ncalls;
|
||||
ev->ev_pncalls = &ncalls;
|
||||
while (ncalls) {
|
||||
ncalls--;
|
||||
ev->ev_ncalls = ncalls;
|
||||
(*ev->ev_callback)((int)ev->ev_fd, ev->ev_res, ev->ev_arg);
|
||||
if (event_gotsig || base->event_break)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -674,35 +585,34 @@ void
|
||||
event_set(struct event *ev, evutil_socket_t fd, short events,
|
||||
void (*callback)(evutil_socket_t, short, void *), void *arg)
|
||||
{
|
||||
event_head_set(EVHEAD(ev), EVENT_CB(event_legacy_handler), NULL);
|
||||
|
||||
/* Take the current base - caller needs to set the real base later */
|
||||
ev->ev_base = current_base;
|
||||
|
||||
ev->ev_flags = 0;
|
||||
ev->ev_callback = callback;
|
||||
ev->ev_arg = arg;
|
||||
ev->ev_fd = fd;
|
||||
ev->ev_events = events;
|
||||
ev->ev_res = 0;
|
||||
ev->ev_flags = EVLIST_INIT;
|
||||
ev->ev_ncalls = 0;
|
||||
ev->ev_pncalls = NULL;
|
||||
|
||||
min_heap_elem_init(ev);
|
||||
|
||||
/* by default, we put new events into the middle priority */
|
||||
if (current_base)
|
||||
event_priority_set(ev, current_base->nactivequeues/2);
|
||||
if(current_base)
|
||||
ev->ev_pri = current_base->nactivequeues/2;
|
||||
}
|
||||
|
||||
int
|
||||
event_base_set(struct event_base *base, struct event *ev)
|
||||
{
|
||||
/* Only innocent events may be assigned to a different base */
|
||||
if (event_is_active(EVHEAD(ev)) || ev->ev_flags != 0)
|
||||
if (ev->ev_flags != EVLIST_INIT)
|
||||
return (-1);
|
||||
|
||||
ev->ev_base = base;
|
||||
event_head_priority_set(base, EVHEAD(ev), base->nactivequeues/2);
|
||||
ev->ev_pri = base->nactivequeues/2;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -715,7 +625,14 @@ event_base_set(struct event_base *base, struct event *ev)
|
||||
int
|
||||
event_priority_set(struct event *ev, int pri)
|
||||
{
|
||||
return (event_head_priority_set(ev->ev_base, EVHEAD(ev), pri));
|
||||
if (ev->ev_flags & EVLIST_ACTIVE)
|
||||
return (-1);
|
||||
if (pri < 0 || pri >= ev->ev_base->nactivequeues)
|
||||
return (-1);
|
||||
|
||||
ev->ev_pri = pri;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -730,8 +647,8 @@ event_pending(struct event *ev, short event, struct timeval *tv)
|
||||
|
||||
if (ev->ev_flags & EVLIST_INSERTED)
|
||||
flags |= (ev->ev_events & (EV_READ|EV_WRITE));
|
||||
if (event_is_active(EVHEAD(ev)))
|
||||
flags |= event_active_events(EVHEAD(ev));
|
||||
if (ev->ev_flags & EVLIST_ACTIVE)
|
||||
flags |= ev->ev_res;
|
||||
if (ev->ev_flags & EVLIST_TIMEOUT)
|
||||
flags |= EV_TIMEOUT;
|
||||
if (ev->ev_flags & EVLIST_SIGNAL)
|
||||
@ -780,8 +697,8 @@ event_add(struct event *ev, struct timeval *tv)
|
||||
/* Check if it is active due to a timeout. Rescheduling
|
||||
* this timeout before the callback can be executed
|
||||
* removes it from the active list. */
|
||||
if (event_is_active(EVHEAD(ev)) &&
|
||||
(event_active_events(EVHEAD(ev)) & EV_TIMEOUT)) {
|
||||
if ((ev->ev_flags & EVLIST_ACTIVE) &&
|
||||
(ev->ev_res & EV_TIMEOUT)) {
|
||||
/* See if we are just active executing this
|
||||
* event in a loop
|
||||
*/
|
||||
@ -790,7 +707,7 @@ event_add(struct event *ev, struct timeval *tv)
|
||||
*ev->ev_pncalls = 0;
|
||||
}
|
||||
|
||||
event_remove_active(base, EVHEAD(ev));
|
||||
event_queue_remove(base, ev, EVLIST_ACTIVE);
|
||||
}
|
||||
|
||||
gettime(&now);
|
||||
@ -803,13 +720,11 @@ event_add(struct event *ev, struct timeval *tv)
|
||||
event_queue_insert(base, ev, EVLIST_TIMEOUT);
|
||||
}
|
||||
|
||||
if (ev->ev_events & (EV_READ|EV_WRITE)) {
|
||||
if ((ev->ev_flags & EVLIST_INSERTED) == 0 &&
|
||||
!event_is_active(EVHEAD(ev))) {
|
||||
event_queue_insert(base, ev, EVLIST_INSERTED);
|
||||
if ((ev->ev_events & (EV_READ|EV_WRITE)) &&
|
||||
!(ev->ev_flags & (EVLIST_INSERTED|EVLIST_ACTIVE))) {
|
||||
event_queue_insert(base, ev, EVLIST_INSERTED);
|
||||
|
||||
return (evsel->add(evbase, ev));
|
||||
}
|
||||
return (evsel->add(evbase, ev));
|
||||
} else if ((ev->ev_events & EV_SIGNAL) &&
|
||||
!(ev->ev_flags & EVLIST_SIGNAL)) {
|
||||
event_queue_insert(base, ev, EVLIST_SIGNAL);
|
||||
@ -849,8 +764,8 @@ event_del(struct event *ev)
|
||||
if (ev->ev_flags & EVLIST_TIMEOUT)
|
||||
event_queue_remove(base, ev, EVLIST_TIMEOUT);
|
||||
|
||||
if (event_is_active(EVHEAD(ev)))
|
||||
event_remove_active(base, EVHEAD(ev));
|
||||
if (ev->ev_flags & EVLIST_ACTIVE)
|
||||
event_queue_remove(base, ev, EVLIST_ACTIVE);
|
||||
|
||||
if (ev->ev_flags & EVLIST_INSERTED) {
|
||||
event_queue_remove(base, ev, EVLIST_INSERTED);
|
||||
@ -866,16 +781,16 @@ event_del(struct event *ev)
|
||||
void
|
||||
event_active(struct event *ev, int res, short ncalls)
|
||||
{
|
||||
/* If we get different kinds of events, add them together */
|
||||
int was_active = event_is_active(EVHEAD(ev));
|
||||
|
||||
event_make_active(ev->ev_base, EVHEAD(ev), res);
|
||||
|
||||
if (was_active)
|
||||
/* We get different kinds of events, add them together */
|
||||
if (ev->ev_flags & EVLIST_ACTIVE) {
|
||||
ev->ev_res |= res;
|
||||
return;
|
||||
}
|
||||
|
||||
ev->ev_res = res;
|
||||
ev->ev_ncalls = ncalls;
|
||||
ev->ev_pncalls = NULL;
|
||||
event_queue_insert(ev->ev_base, ev, EVLIST_ACTIVE);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -983,6 +898,11 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue)
|
||||
|
||||
ev->ev_flags &= ~queue;
|
||||
switch (queue) {
|
||||
case EVLIST_ACTIVE:
|
||||
base->event_count_active--;
|
||||
TAILQ_REMOVE(base->activequeues[ev->ev_pri],
|
||||
ev, ev_active_next);
|
||||
break;
|
||||
case EVLIST_SIGNAL:
|
||||
TAILQ_REMOVE(&base->sig.signalqueue, ev, ev_signal_next);
|
||||
break;
|
||||
@ -1000,15 +920,25 @@ event_queue_remove(struct event_base *base, struct event *ev, int queue)
|
||||
void
|
||||
event_queue_insert(struct event_base *base, struct event *ev, int queue)
|
||||
{
|
||||
if (ev->ev_flags & queue)
|
||||
if (ev->ev_flags & queue) {
|
||||
/* Double insertion is possible for active events */
|
||||
if (queue & EVLIST_ACTIVE)
|
||||
return;
|
||||
|
||||
event_errx(1, "%s: %p(fd %d) already on queue %x", __func__,
|
||||
ev, ev->ev_fd, queue);
|
||||
}
|
||||
|
||||
if (~ev->ev_flags & EVLIST_INTERNAL)
|
||||
base->event_count++;
|
||||
|
||||
ev->ev_flags |= queue;
|
||||
switch (queue) {
|
||||
case EVLIST_ACTIVE:
|
||||
base->event_count_active++;
|
||||
TAILQ_INSERT_TAIL(base->activequeues[ev->ev_pri],
|
||||
ev,ev_active_next);
|
||||
break;
|
||||
case EVLIST_SIGNAL:
|
||||
TAILQ_INSERT_TAIL(&base->sig.signalqueue, ev, ev_signal_next);
|
||||
break;
|
||||
|
52
event.h
52
event.h
@ -192,11 +192,11 @@ typedef unsigned short u_short;
|
||||
/* EVLIST_X_ Private space: 0x1000-0xf000 */
|
||||
#define EVLIST_ALL (0xf000 | 0x9f)
|
||||
|
||||
#define EV_TIMEOUT 0x0001
|
||||
#define EV_READ 0x0002
|
||||
#define EV_WRITE 0x0004
|
||||
#define EV_SIGNAL 0x0008
|
||||
#define EV_PERSIST 0x0800 /* Persistant event */
|
||||
#define EV_TIMEOUT 0x01
|
||||
#define EV_READ 0x02
|
||||
#define EV_WRITE 0x04
|
||||
#define EV_SIGNAL 0x08
|
||||
#define EV_PERSIST 0x10 /* Persistant event */
|
||||
|
||||
/* Fix so that ppl dont have to run with <sys/queue.h> */
|
||||
#ifndef TAILQ_ENTRY
|
||||
@ -208,36 +208,13 @@ struct { \
|
||||
}
|
||||
#endif /* !TAILQ_ENTRY */
|
||||
|
||||
#define EVHEAD(x) ((struct event_head *)(x))
|
||||
|
||||
struct event_base;
|
||||
|
||||
/** a structure common to all events
|
||||
*
|
||||
* struct event_head contains elements common to all event types.
|
||||
* it needs to be the first element of any structure that defines
|
||||
* a new event type.
|
||||
*/
|
||||
struct event_head {
|
||||
TAILQ_ENTRY (event_head) (ev_active_next);
|
||||
int ev_pri; /*!< smaller numbers are higher priority */
|
||||
int ev_res; /*!< result passed to event callback */
|
||||
int ev_flags; /*!< keeps track of initialization and activation */
|
||||
|
||||
void (*ev_cb)(struct event_base *, struct event_head *,
|
||||
int events, void *);
|
||||
void *ev_cb_arg;
|
||||
};
|
||||
|
||||
struct event {
|
||||
struct event_head head;
|
||||
|
||||
TAILQ_ENTRY (event) (ev_next);
|
||||
TAILQ_ENTRY (event) ev_next;
|
||||
TAILQ_ENTRY (event) ev_active_next;
|
||||
TAILQ_ENTRY (event) ev_signal_next;
|
||||
unsigned int min_heap_idx; /* for managing timeouts */
|
||||
|
||||
int ev_flags;
|
||||
|
||||
struct event_base *ev_base;
|
||||
|
||||
evutil_socket_t ev_fd;
|
||||
@ -247,8 +224,13 @@ struct event {
|
||||
|
||||
struct timeval ev_timeout;
|
||||
|
||||
int ev_pri; /* smaller numbers are higher priority */
|
||||
|
||||
void (*ev_callback)(evutil_socket_t, short, void *arg);
|
||||
void *ev_arg;
|
||||
|
||||
int ev_res; /* result passed to event callback */
|
||||
int ev_flags;
|
||||
};
|
||||
|
||||
#define EVENT_SIGNAL(ev) (int)(ev)->ev_fd
|
||||
@ -482,7 +464,7 @@ int event_base_loopbreak(struct event_base *);
|
||||
*/
|
||||
#define evtimer_del(ev) event_del(ev)
|
||||
#define evtimer_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv)
|
||||
#define evtimer_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT)
|
||||
#define evtimer_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
|
||||
|
||||
/**
|
||||
* Add a timeout event.
|
||||
@ -511,14 +493,14 @@ int event_base_loopbreak(struct event_base *);
|
||||
#define timeout_del(ev) event_del(ev)
|
||||
|
||||
#define timeout_pending(ev, tv) event_pending(ev, EV_TIMEOUT, tv)
|
||||
#define timeout_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT)
|
||||
#define timeout_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
|
||||
|
||||
#define signal_add(ev, tv) event_add(ev, tv)
|
||||
#define signal_set(ev, x, cb, arg) \
|
||||
event_set(ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)
|
||||
#define signal_del(ev) event_del(ev)
|
||||
#define signal_pending(ev, tv) event_pending(ev, EV_SIGNAL, tv)
|
||||
#define signal_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT)
|
||||
#define signal_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
|
||||
|
||||
/**
|
||||
Prepare an event structure to be added.
|
||||
@ -659,9 +641,9 @@ int event_pending(struct event *, short, struct timeval *);
|
||||
initialized
|
||||
*/
|
||||
#ifdef WIN32
|
||||
#define event_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT && (ev)->ev_fd != (int)INVALID_HANDLE_VALUE)
|
||||
#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT && (ev)->ev_fd != (int)INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
#define event_initialized(ev) (EVHEAD(ev)->ev_flags & EVLIST_INIT)
|
||||
#define event_initialized(ev) ((ev)->ev_flags & EVLIST_INIT)
|
||||
#endif
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user