#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)
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)
{
#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;
}
}
+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)
{
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);
#include "event-config.h"
#include "evutil.h"
+#include "defer-internal.h"
#include <sys/queue.h>
/* minimum allocation for a chain. */
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;
};
*/
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