Avoid needlessly calling evthread_notify_base() when the loop is not running

Also make sure that we always hold the base lock when calling evthread_notify_base.
This commit is contained in:
Nick Mathewson 2010-09-08 13:02:58 -04:00
parent 495ed66705
commit c7a06bfaee
2 changed files with 20 additions and 9 deletions

16
event.c
View File

@ -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);

View File

@ -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