Facility to make evbuffers get their callbacks deferred.

svn:r1154
This commit is contained in:
Nick Mathewson 2009-04-10 20:43:08 +00:00
parent decdacfaf8
commit b29b875d84
3 changed files with 55 additions and 2 deletions

View File

@ -134,6 +134,7 @@ static int use_mmap = 1;
#define CHAIN_PINNED(ch) (((ch)->flags & EVBUFFER_MEM_PINNED_ANY) != 0)
static void evbuffer_chain_align(struct evbuffer_chain *chain);
static void evbuffer_deferred_callback(struct deferred_cb *cb, void *arg);
static struct evbuffer_chain *
evbuffer_chain_new(size_t size)
@ -260,6 +261,18 @@ evbuffer_new(void)
return (buffer);
}
int
evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base)
{
EVBUFFER_LOCK(buffer, EVTHREAD_WRITE);
buffer->ev_base = base;
buffer->deferred_cbs = 1;
event_deferred_cb_init(&buffer->deferred,
evbuffer_deferred_callback, buffer);
EVBUFFER_UNLOCK(buffer, EVTHREAD_WRITE);
return 0;
}
int
evbuffer_enable_locking(struct evbuffer *buf, void *lock)
{
@ -284,8 +297,8 @@ evbuffer_enable_locking(struct evbuffer *buf, void *lock)
#endif
}
static inline void
evbuffer_invoke_callbacks(struct evbuffer *buffer)
static void
evbuffer_run_callbacks(struct evbuffer *buffer)
{
struct evbuffer_cb_entry *cbent, *next;
struct evbuffer_cb_info info;
@ -328,6 +341,28 @@ evbuffer_invoke_callbacks(struct evbuffer *buffer)
}
}
static inline void
evbuffer_invoke_callbacks(struct evbuffer *buffer)
{
if (buffer->deferred_cbs) {
event_deferred_cb_schedule(buffer->ev_base, &buffer->deferred);
} else {
evbuffer_run_callbacks(buffer);
}
}
static void
evbuffer_deferred_callback(struct deferred_cb *cb, void *arg)
{
struct evbuffer *buffer = arg;
static int which = 0;
printf("FOO #%d\n", which++);
EVBUFFER_LOCK(buffer, EVTHREAD_WRITE);
evbuffer_run_callbacks(buffer);
EVBUFFER_UNLOCK(buffer, EVTHREAD_WRITE);
}
static void
evbuffer_remove_all_callbacks(struct evbuffer *buffer)
{
@ -351,6 +386,8 @@ evbuffer_free(struct evbuffer *buffer)
evbuffer_chain_free(chain);
}
evbuffer_remove_all_callbacks(buffer);
if (buffer->deferred_cbs)
event_deferred_cb_cancel(buffer->ev_base, &buffer->deferred);
if (buffer->own_lock)
EVTHREAD_FREE_LOCK(buffer->lock);
mm_free(buffer);

View File

@ -33,6 +33,7 @@ extern "C" {
#include "event-config.h"
#include "evutil.h"
#include "defer-internal.h"
#include <sys/queue.h>
/* minimum allocation for a chain. */
@ -78,9 +79,14 @@ struct evbuffer {
unsigned own_lock : 1;
unsigned freeze_start : 1;
unsigned freeze_end : 1;
unsigned deferred_cbs : 1;
struct event_base *ev_base;
int lock_count;
struct deferred_cb deferred;
TAILQ_HEAD(evbuffer_cb_queue, evbuffer_cb_entry) callbacks;
};

View File

@ -587,6 +587,16 @@ int evbuffer_freeze(struct evbuffer *buf, int at_front);
*/
int evbuffer_unfreeze(struct evbuffer *buf, int at_front);
struct event_base;
/**
Force all the callbacks on an evbuffer to be run, not immediately after
the evbuffer is altered, but instead from inside the event loop.
This can be used to serialize all the callbacks to a single thread
of execution.
*/
int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base);
#ifdef __cplusplus
}
#endif