]> granicus.if.org Git - libevent/commitdiff
separate signal events from io events
authorNiels Provos <provos@gmail.com>
Sat, 3 May 2008 21:37:33 +0000 (21:37 +0000)
committerNiels Provos <provos@gmail.com>
Sat, 3 May 2008 21:37:33 +0000 (21:37 +0000)
svn:r760

ChangeLog
event-internal.h
event.c
include/event2/event_struct.h
signal.c

index 8122ac15efd506ecdbbd661d14e70b2eb4bd63db..b3bc09ccf0cd466fc904278ce9482e7957112328 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -86,6 +86,7 @@ Changes in current version:
  o introduce evbuffer_contiguous_space() api that tells a user how much data is available in the first buffer chain
  o introduce evbuffer_reserve_space() and evbuffer_commit_space() to make processing in filters more efficient.
  o reduce system calls for getting current time by caching it.
+ o separate signal events from io events; making the code less complex.
        
 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 e80171ee8659a9b626b25d4a8cf4906ed87fa86e..10fd5d5b793f0be4556d56ba74418e931af678f4 100644 (file)
@@ -36,6 +36,16 @@ extern "C" {
 #include "evsignal.h"
 #include "mm-internal.h"
 
+/* map union members back */
+
+/* mutually exclusive */
+#define ev_next                _ev.ev_io.ev_next
+#define ev_signal_next _ev.ev_signal.ev_signal_next
+
+/* used only by signals */
+#define ev_ncalls      _ev.ev_signal.ev_ncalls
+#define ev_pncalls     _ev.ev_signal.ev_pncalls
+
 struct eventop {
        const char *name;
        void *(*init)(struct event_base *);
diff --git a/event.c b/event.c
index 0215deaeaf867bf99c039ddffacfb9c04e87ea0c..740d8f08de78a851c805c75bccad5be5a5625bea 100644 (file)
--- a/event.c
+++ b/event.c
@@ -136,6 +136,8 @@ static int  timeout_next(struct event_base *, struct timeval **);
 static void    timeout_process(struct event_base *);
 static void    timeout_correct(struct event_base *, struct timeval *);
 
+static void    event_signal_closure(struct event_base *, struct event *ev);
+
 static void
 detect_monotonic(void)
 {
@@ -360,6 +362,23 @@ event_haveevents(struct event_base *base)
        return (base->event_count > 0);
 }
 
+static void
+event_signal_closure(struct event_base *base, struct event *ev)
+{
+       short ncalls;
+
+       /* 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;
+       }
+}
+
 /*
  * Active events are stored in priority queues.  Lower priorities are always
  * process before higher priorities.  Low priority events can starve high
@@ -372,7 +391,6 @@ event_process_active(struct event_base *base)
        struct event *ev;
        struct event_list *activeq = NULL;
        int i;
-       short ncalls;
 
        EVTHREAD_ACQUIRE_LOCK(base, EVTHREAD_WRITE, th_base_lock);
 
@@ -394,16 +412,13 @@ event_process_active(struct event_base *base)
                EVTHREAD_RELEASE_LOCK(base,
                    EVTHREAD_WRITE, th_base_lock);
 
-               /* 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;
-               }
+               if (ev->ev_closure != NULL)
+                       (*ev->ev_closure)(base, ev);
+               else
+                       (*ev->ev_callback)(
+                               (int)ev->ev_fd, ev->ev_res, ev->ev_arg);
+               if (event_gotsig || base->event_break)
+                       return;
                EVTHREAD_ACQUIRE_LOCK(base, EVTHREAD_WRITE, th_base_lock);
        }
 
@@ -655,6 +670,15 @@ event_set(struct event *ev, evutil_socket_t fd, short events,
        ev->ev_ncalls = 0;
        ev->ev_pncalls = NULL;
 
+       if (events & EV_SIGNAL) {
+               if ((events & (EV_READ|EV_WRITE)) != 0)
+                       event_errx(1, "%s: EV_SIGNAL incompatible use",
+                           __func__);
+               ev->ev_closure = event_signal_closure;
+       } else {
+               ev->ev_closure = NULL;
+       }
+
        min_heap_elem_init(ev);
 
        /* by default, we put new events into the middle priority */
@@ -804,12 +828,14 @@ event_add_internal(struct event *ev, struct timeval *tv)
                 * removes it from the active list. */
                if ((ev->ev_flags & EVLIST_ACTIVE) &&
                    (ev->ev_res & EV_TIMEOUT)) {
-                       /* See if we are just active executing this
-                        * event in a loop
-                        */
-                       if (ev->ev_ncalls && ev->ev_pncalls) {
-                               /* Abort loop */
-                               *ev->ev_pncalls = 0;
+                       if (ev->ev_flags & EVLIST_SIGNAL) {
+                               /* See if we are just active executing
+                                * this event in a loop
+                                */
+                               if (ev->ev_ncalls && ev->ev_pncalls) {
+                                       /* Abort loop */
+                                       *ev->ev_pncalls = 0;
+                               }
                        }
                        
                        event_queue_remove(base, ev, EVLIST_ACTIVE);
@@ -880,9 +906,11 @@ event_del_internal(struct event *ev)
        assert(!(ev->ev_flags & ~EVLIST_ALL));
 
        /* See if we are just active executing this event in a loop */
-       if (ev->ev_ncalls && ev->ev_pncalls) {
-               /* Abort loop */
-               *ev->ev_pncalls = 0;
+       if (ev->ev_flags & EVLIST_SIGNAL) {
+               if (ev->ev_ncalls && ev->ev_pncalls) {
+                       /* Abort loop */
+                       *ev->ev_pncalls = 0;
+               }
        }
 
        if (ev->ev_flags & EVLIST_TIMEOUT)
@@ -931,8 +959,12 @@ event_active_internal(struct event *ev, int res, short ncalls)
        base = ev->ev_base;
 
        ev->ev_res = res;
-       ev->ev_ncalls = ncalls;
-       ev->ev_pncalls = NULL;
+
+       if (ev->ev_flags & EVLIST_SIGNAL) {
+               ev->ev_ncalls = ncalls;
+               ev->ev_pncalls = NULL;
+       }
+
        event_queue_insert(base, ev, EVLIST_ACTIVE);
 }
 
index 4256d89fa5be79fa205fe16e75d967c05cad29bd..b85e4528fbdc36ec3dffc24af711f0db16f8d9ac 100644 (file)
@@ -85,22 +85,35 @@ struct {                                                            \
 
 struct event_base;
 struct event {
-       TAILQ_ENTRY (event) ev_next;
-       TAILQ_ENTRY (event) ev_active_next;
-       TAILQ_ENTRY (event) ev_signal_next;
+       TAILQ_ENTRY (event) (ev_active_next);
        unsigned int min_heap_idx;      /* for managing timeouts */
 
        struct event_base *ev_base;
 
        evutil_socket_t ev_fd;
+       union {
+               /* used by io events */
+               struct {
+                       TAILQ_ENTRY (event) (ev_next);
+               } ev_io;
+
+               /* used by signal events */
+               struct {
+                       TAILQ_ENTRY (event) (ev_signal_next);
+                       short ev_ncalls;
+                       /* Allows deletes in callback */
+                       short *ev_pncalls;
+               } ev_signal;
+       } _ev;
+
        short ev_events;
-       short ev_ncalls;
-       short *ev_pncalls;      /* Allows deletes in callback */
 
        struct timeval ev_timeout;
 
        int ev_pri;             /* smaller numbers are higher priority */
 
+       /* allows us to adopt for different types of events */
+       void (*ev_closure)(struct event_base *, struct event *);
        void (*ev_callback)(evutil_socket_t, short, void *arg);
        void *ev_arg;
 
index 4bfe9bcdfc293fd4996ec7c8d37e132fe85e099e..e9b8664e9d56f8cffa3de636c32d0ce7a411a4f3 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -188,8 +188,6 @@ evsignal_add(struct event *ev)
        struct event_base *base = ev->ev_base;
        struct evsignal_info *sig = &ev->ev_base->sig;
 
-       if (ev->ev_events & (EV_READ|EV_WRITE))
-               event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
        evsignal = EVENT_SIGNAL(ev);
 
        event_debug(("%s: %p: changing signal handler", __func__, ev));