From 438f9ed26c63bd47c9e1a5cbe52731996f05c3ea Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 23 Nov 2009 15:53:24 -0500 Subject: [PATCH] Add the abilitity to mark some buffer callbacks as never-deferred. --- buffer.c | 48 +++++++++++++++++++++-------------------- bufferevent.c | 4 ++-- include/event2/buffer.h | 3 +++ 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/buffer.c b/buffer.c index 4111a8e4..be9c7ec9 100644 --- a/buffer.c +++ b/buffer.c @@ -123,13 +123,6 @@ static int use_mmap = 1; /* Mask of all internal-use-only flags. */ #define EVBUFFER_CB_INTERNAL_FLAGS 0xffff0000 -#if 0 -/* Flag set on suspended callbacks. */ -#define EVBUFFER_CB_SUSPENDED 0x00010000 -/* Flag set if we should invoke the callback on wakeup. */ -#define EVBUFFER_CB_CALL_ON_UNSUSPEND 0x00020000 -#endif - /* Flag set if the callback is using the cb_obsolete function pointer */ #define EVBUFFER_CB_OBSOLETE 0x00040000 @@ -334,11 +327,23 @@ evbuffer_set_parent(struct evbuffer *buf, struct bufferevent *bev) } static void -evbuffer_run_callbacks(struct evbuffer *buffer) +evbuffer_run_callbacks(struct evbuffer *buffer, int running_deferred) { struct evbuffer_cb_entry *cbent, *next; struct evbuffer_cb_info info; size_t new_size; + uint32_t mask, masked_val; + + if (running_deferred) { + mask = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED; + masked_val = EVBUFFER_CB_ENABLED; + } else if (buffer->deferred_cbs) { + mask = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED; + masked_val = EVBUFFER_CB_NODEFER|EVBUFFER_CB_ENABLED; + } else { + mask = EVBUFFER_CB_ENABLED; + masked_val = EVBUFFER_CB_ENABLED; + } ASSERT_EVBUFFER_LOCKED(buffer); @@ -362,18 +367,15 @@ evbuffer_run_callbacks(struct evbuffer *buffer) /* Get the 'next' pointer now in case this callback decides * to remove itself or something. */ next = TAILQ_NEXT(cbent, next); - if ((cbent->flags & EVBUFFER_CB_ENABLED)) { -#if 0 - if ((cbent->flags & EVBUFFER_CB_SUSPENDED)) - cbent->flags |= EVBUFFER_CB_CALL_ON_UNSUSPEND; - else -#endif - if ((cbent->flags & EVBUFFER_CB_OBSOLETE)) - cbent->cb.cb_obsolete(buffer, - info.orig_size, new_size, cbent->cbarg); - else - cbent->cb.cb_func(buffer, &info, cbent->cbarg); - } + + if ((cbent->flags & mask) != masked_val) + continue; + + if ((cbent->flags & EVBUFFER_CB_OBSOLETE)) + cbent->cb.cb_obsolete(buffer, + info.orig_size, new_size, cbent->cbarg); + else + cbent->cb.cb_func(buffer, &info, cbent->cbarg); } } @@ -388,9 +390,9 @@ evbuffer_invoke_callbacks(struct evbuffer *buffer) bufferevent_incref(buffer->parent); EVBUFFER_UNLOCK(buffer); event_deferred_cb_schedule(buffer->cb_queue, &buffer->deferred); - } else { - evbuffer_run_callbacks(buffer); } + + evbuffer_run_callbacks(buffer, 0); } static void @@ -403,7 +405,7 @@ evbuffer_deferred_callback(struct deferred_cb *cb, void *arg) * lock */ EVBUFFER_LOCK(buffer); parent = buffer->parent; - evbuffer_run_callbacks(buffer); + evbuffer_run_callbacks(buffer, 1); _evbuffer_decref_and_unlock(buffer); if (parent) bufferevent_free(parent); diff --git a/bufferevent.c b/bufferevent.c index 20b2afb0..2794cff2 100644 --- a/bufferevent.c +++ b/bufferevent.c @@ -443,8 +443,8 @@ bufferevent_setwatermark(struct bufferevent *bufev, short events, bufev); } evbuffer_cb_set_flags(bufev->input, - bufev_private->read_watermarks_cb, - EVBUFFER_CB_ENABLED); + bufev_private->read_watermarks_cb, + EVBUFFER_CB_ENABLED|EVBUFFER_CB_NODEFER); if (evbuffer_get_length(bufev->input) > highmark) bufferevent_wm_suspend_read(bufev); diff --git a/include/event2/buffer.h b/include/event2/buffer.h index 2a8e8378..0fb6dffd 100644 --- a/include/event2/buffer.h +++ b/include/event2/buffer.h @@ -610,6 +610,9 @@ int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg * should not be invoked. */ #define EVBUFFER_CB_ENABLED 1 +/* Experimental cb flag: "never deferred" */ +#define EVBUFFER_CB_NODEFER 2 + /** Change the flags that are set for a callback on a buffer by adding more. @param buffer the evbuffer that the callback is watching.