Make getting metadata user data a lock free operation

pull/3794/head
Craig Tiller 9 years ago
parent 63bda56884
commit 8344daa1df
  1. 37
      src/core/transport/metadata.c

@ -62,6 +62,8 @@
#define REF_MD_LOCKED(s) ref_md_locked((s))
#endif
typedef void (*destroy_user_data_func)(void *user_data);
typedef struct internal_string {
/* must be byte compatible with grpc_mdstr */
gpr_slice slice;
@ -88,8 +90,8 @@ typedef struct internal_metadata {
/* private only data */
gpr_mu mu_user_data;
void *user_data;
void (*destroy_user_data)(void *user_data);
gpr_atm destroy_user_data;
gpr_atm user_data;
grpc_mdctx *context;
struct internal_metadata *bucket_next;
@ -201,12 +203,14 @@ static void discard_metadata(grpc_mdctx *ctx) {
for (i = 0; i < ctx->mdtab_capacity; i++) {
cur = ctx->mdtab[i];
while (cur) {
void *user_data = (void *)gpr_atm_no_barrier_load(&cur->user_data);
GPR_ASSERT(gpr_atm_acq_load(&cur->refcnt) == 0);
next = cur->bucket_next;
INTERNAL_STRING_UNREF(cur->key);
INTERNAL_STRING_UNREF(cur->value);
if (cur->user_data) {
cur->destroy_user_data(cur->user_data);
if (user_data != NULL) {
((destroy_user_data_func)gpr_atm_no_barrier_load(
&cur->destroy_user_data))(user_data);
}
gpr_mu_destroy(&cur->mu_user_data);
gpr_free(cur);
@ -392,12 +396,14 @@ static void gc_mdtab(grpc_mdctx *ctx) {
for (i = 0; i < ctx->mdtab_capacity; i++) {
prev_next = &ctx->mdtab[i];
for (md = ctx->mdtab[i]; md; md = next) {
void *user_data = (void *)gpr_atm_no_barrier_load(&md->user_data);
next = md->bucket_next;
if (gpr_atm_acq_load(&md->refcnt) == 0) {
INTERNAL_STRING_UNREF(md->key);
INTERNAL_STRING_UNREF(md->value);
if (md->user_data) {
md->destroy_user_data(md->user_data);
((destroy_user_data_func)gpr_atm_no_barrier_load(
&md->destroy_user_data))(user_data);
}
gpr_free(md);
*prev_next = next;
@ -473,8 +479,8 @@ grpc_mdelem *grpc_mdelem_from_metadata_strings(grpc_mdctx *ctx,
md->context = ctx;
md->key = key;
md->value = value;
md->user_data = NULL;
md->destroy_user_data = NULL;
md->user_data = 0;
md->destroy_user_data = 0;
md->bucket_next = ctx->mdtab[hash % ctx->mdtab_capacity];
gpr_mu_init(&md->mu_user_data);
#ifdef GRPC_METADATA_REFCOUNT_DEBUG
@ -588,13 +594,14 @@ size_t grpc_mdctx_get_mdtab_free_test_only(grpc_mdctx *ctx) {
return ctx->mdtab_free;
}
void *grpc_mdelem_get_user_data(grpc_mdelem *md,
void (*if_destroy_func)(void *)) {
void *grpc_mdelem_get_user_data(grpc_mdelem *md, void (*destroy_func)(void *)) {
internal_metadata *im = (internal_metadata *)md;
void *result;
gpr_mu_lock(&im->mu_user_data);
result = im->destroy_user_data == if_destroy_func ? im->user_data : NULL;
gpr_mu_unlock(&im->mu_user_data);
if (gpr_atm_acq_load(&im->destroy_user_data) == (gpr_atm)destroy_func) {
return (void *)gpr_atm_no_barrier_load(&im->user_data);
} else {
return NULL;
}
return result;
}
@ -603,7 +610,7 @@ void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
internal_metadata *im = (internal_metadata *)md;
GPR_ASSERT((user_data == NULL) == (destroy_func == NULL));
gpr_mu_lock(&im->mu_user_data);
if (im->destroy_user_data) {
if (gpr_atm_no_barrier_load(&im->destroy_user_data)) {
/* user data can only be set once */
gpr_mu_unlock(&im->mu_user_data);
if (destroy_func != NULL) {
@ -611,8 +618,8 @@ void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
}
return;
}
im->destroy_user_data = destroy_func;
im->user_data = user_data;
gpr_atm_no_barrier_store(&im->user_data, (gpr_atm)user_data);
gpr_atm_rel_store(&im->destroy_user_data, (gpr_atm)destroy_func);
gpr_mu_unlock(&im->mu_user_data);
}

Loading…
Cancel
Save