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)
{
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
struct event *ev;
struct event_list *activeq = NULL;
int i;
- short ncalls;
EVTHREAD_ACQUIRE_LOCK(base, EVTHREAD_WRITE, th_base_lock);
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);
}
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 */
* 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);
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)
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);
}
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;