diff --git a/event.c b/event.c index ee741e7b..0c8238d7 100644 --- a/event.c +++ b/event.c @@ -471,7 +471,7 @@ static void notify_base_cbq_callback(struct deferred_cb_queue *cb, void *baseptr) { struct event_base *base = baseptr; - if (!EVBASE_IN_THREAD(base)) + if (EVBASE_NEED_NOTIFY(base)) evthread_notify_base(base); } @@ -1390,18 +1390,20 @@ event_loopbreak(void) int event_base_loopbreak(struct event_base *event_base) { + int r = 0; if (event_base == NULL) return (-1); EVBASE_ACQUIRE_LOCK(event_base, th_base_lock); event_base->event_break = 1; - EVBASE_RELEASE_LOCK(event_base, th_base_lock); - if (!EVBASE_IN_THREAD(event_base)) { - return evthread_notify_base(event_base); + if (EVBASE_NEED_NOTIFY(event_base)) { + r = evthread_notify_base(event_base); } else { - return (0); + r = (0); } + EVBASE_RELEASE_LOCK(event_base, th_base_lock); + return r; } int @@ -2050,7 +2052,7 @@ event_add_internal(struct event *ev, const struct timeval *tv, } /* if we are not in the right thread, we need to wake up the loop */ - if (res != -1 && notify && !EVBASE_IN_THREAD(base)) + if (res != -1 && notify && EVBASE_NEED_NOTIFY(base)) evthread_notify_base(base); _event_debug_note_add(ev); @@ -2144,7 +2146,7 @@ event_del_internal(struct event *ev) } /* if we are not in the right thread, we need to wake up the loop */ - if (res != -1 && notify && !EVBASE_IN_THREAD(base)) + if (res != -1 && notify && EVBASE_NEED_NOTIFY(base)) evthread_notify_base(base); _event_debug_note_del(ev); diff --git a/evthread-internal.h b/evthread-internal.h index d710939a..b7286ded 100644 --- a/evthread-internal.h +++ b/evthread-internal.h @@ -48,12 +48,20 @@ extern int _evthread_lock_debugging_enabled; #define EVTHREAD_GET_ID() \ (_evthread_id_fn ? _evthread_id_fn() : 1) -/** Return true iff we're in the thread that is currently running a given - * event_base's loop. */ +/** Return true iff we're in the thread that is currently (or most recently) + * running a given event_base's loop. Requires lock. */ #define EVBASE_IN_THREAD(base) \ (_evthread_id_fn == NULL || \ (base)->th_owner_id == _evthread_id_fn()) +/** Return true iff we need to notify the base's main thread about changes to + * its state, because it's currently running the main loop in another + * thread. Requires lock. */ +#define EVBASE_NEED_NOTIFY(base) \ + (_evthread_id_fn != NULL && \ + (base)->running_loop && \ + (base)->th_owner_id != _evthread_id_fn()) + /** Allocate a new lock, and store it in lockvar, a void*. Sets lockvar to NULL if locking is not enabled. */ #define EVTHREAD_ALLOC_LOCK(lockvar, locktype) \ @@ -196,6 +204,7 @@ EVLOCK_TRY_LOCK(void *lock) #define EVLOCK_UNLOCK2(lock1,lock2,mode1,mode2) _EVUTIL_NIL_STMT #define EVBASE_IN_THREAD(base) 1 +#define EVBASE_NEED_NOTIFY(base) 0 #define EVBASE_ACQUIRE_LOCK(base, lock) _EVUTIL_NIL_STMT #define EVBASE_RELEASE_LOCK(base, lock) _EVUTIL_NIL_STMT #define EVLOCK_ASSERT_LOCKED(lock) _EVUTIL_NIL_STMT