Add a slice allocation scheme

reviewable/pr8239/r2
Craig Tiller 9 years ago
parent 287928c69c
commit b635c61e04
  1. 75
      src/core/lib/iomgr/buffer_pool.c
  2. 14
      src/core/lib/iomgr/buffer_pool.h

@ -220,6 +220,52 @@ static bool bpreclaim(grpc_exec_ctx *exec_ctx, grpc_buffer_pool *buffer_pool,
return true;
}
/*******************************************************************************
* bu_slice: a slice implementation that is backed by a grpc_buffer_user
*/
typedef struct {
gpr_slice_refcount base;
gpr_refcount refs;
grpc_buffer_user *buffer_user;
size_t size;
} bu_slice_refcount;
static void bu_slice_ref(void *p) {
bu_slice_refcount *rc = p;
gpr_ref(&rc->refs);
}
static void bu_slice_unref(void *p) {
bu_slice_refcount *rc = p;
if (gpr_unref(&rc->refs)) {
/* TODO(ctiller): this is dangerous, but I think safe for now:
we have no guarantee here that we're at a safe point for creating an
execution context, but we have no way of writing this code otherwise.
In the future: consider lifting gpr_slice to grpc, and offering an
internal_{ref,unref} pair that is execution context aware. Alternatively,
make exec_ctx be thread local and 'do the right thing' (whatever that is)
if NULL */
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_buffer_user_free(&exec_ctx, rc->buffer_user, rc->size);
grpc_exec_ctx_finish(&exec_ctx);
}
}
static gpr_slice bu_slice_create(grpc_buffer_user *buffer_user, size_t size) {
bu_slice_refcount *rc = gpr_malloc(sizeof(bu_slice_refcount) + size);
rc->base.ref = bu_slice_ref;
rc->base.unref = bu_slice_unref;
gpr_ref_init(&rc->refs, 1);
rc->buffer_user = buffer_user;
rc->size = size;
gpr_slice slice;
slice.refcount = &rc->base;
slice.data.refcounted.bytes = (uint8_t *)(rc + 1);
slice.data.refcounted.length = size;
return slice;
}
/*******************************************************************************
* grpc_buffer_pool internal implementation
*/
@ -284,6 +330,20 @@ static void bu_destroy(grpc_exec_ctx *exec_ctx, void *bu, grpc_error *error) {
grpc_buffer_pool_internal_unref(exec_ctx, buffer_user->buffer_pool);
}
static void bu_allocated_slices(grpc_exec_ctx *exec_ctx, void *ts,
grpc_error *error) {
grpc_buffer_user_slice_allocator *alloc_temp_storage = ts;
if (error == GRPC_ERROR_NONE) {
for (size_t i = 0; i < alloc_temp_storage->count; i++) {
gpr_slice_buffer_add(alloc_temp_storage->dest,
bu_slice_create(alloc_temp_storage->buffer_user,
alloc_temp_storage->length));
}
}
grpc_closure_run(exec_ctx, alloc_temp_storage->on_done,
GRPC_ERROR_REF(error));
}
typedef struct {
int64_t size;
grpc_buffer_pool *buffer_pool;
@ -491,3 +551,18 @@ void grpc_buffer_user_finish_reclaimation(grpc_exec_ctx *exec_ctx,
&buffer_user->buffer_pool->bpreclaimation_done_closure,
GRPC_ERROR_NONE, false);
}
void grpc_buffer_user_alloc_slices(
grpc_exec_ctx *exec_ctx, grpc_buffer_user *buffer_user,
grpc_buffer_user_slice_allocator *alloc_temp_storage, size_t length,
size_t count, gpr_slice_buffer *dest, grpc_closure *on_done) {
grpc_closure_init(&alloc_temp_storage->on_allocated, bu_allocated_slices,
alloc_temp_storage);
alloc_temp_storage->on_done = on_done;
alloc_temp_storage->length = length;
alloc_temp_storage->count = count;
alloc_temp_storage->dest = dest;
alloc_temp_storage->buffer_user = buffer_user;
grpc_buffer_user_alloc(exec_ctx, buffer_user, count * length,
&alloc_temp_storage->on_allocated);
}

@ -98,4 +98,18 @@ void grpc_buffer_user_post_reclaimer(grpc_exec_ctx *exec_ctx,
void grpc_buffer_user_finish_reclaimation(grpc_exec_ctx *exec_ctx,
grpc_buffer_user *buffer_user);
typedef struct grpc_buffer_user_slice_allocator {
grpc_closure on_allocated;
grpc_closure *on_done;
size_t length;
size_t count;
gpr_slice_buffer *dest;
grpc_buffer_user *buffer_user;
} grpc_buffer_user_slice_allocator;
void grpc_buffer_user_alloc_slices(
grpc_exec_ctx *exec_ctx, grpc_buffer_user *buffer_user,
grpc_buffer_user_slice_allocator *alloc_temp_storage, size_t length,
size_t count, gpr_slice_buffer *dest, grpc_closure *on_done);
#endif /* GRPC_CORE_LIB_IOMGR_BUFFER_POOL_H */

Loading…
Cancel
Save