]> granicus.if.org Git - libevent/commitdiff
rollback r594: restructuring to make event activation independent.
authorNiels Provos <provos@gmail.com>
Mon, 24 Dec 2007 22:49:30 +0000 (22:49 +0000)
committerNiels Provos <provos@gmail.com>
Mon, 24 Dec 2007 22:49:30 +0000 (22:49 +0000)
changes are going to wait for api design

svn:r612

ChangeLog
event-internal.h
event.c
event.h

index 5793e9e65aae5f08c57710609e79804b153130b9..d4f473b85c6c4355ba6618a885dc539bdb4773d3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index c1f4a2dc8d7abaf0810f0b3686af20abb9ccb434..f61757c118bb62d62bd072a409c055d0f5c9f88b 100644 (file)
@@ -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)
diff --git a/event.c b/event.c
index 4c19915220599e55ea408082cc79229088ccea5c..9b54cfcc1bb54fa7f6d4b0fe582e482a858bdb7d 100644 (file)
--- a/event.c
+++ b/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;
diff --git a/event.h b/event.h
index 9e5c4eaac9a4dd986573c637a821ea9ac4dcb767..cbc8f1b70d7db8a0b80e8896a6bbce602c712a57 100644 (file)
--- a/event.h
+++ b/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