From aef25da3e8efbc1c5b60ef35d7afbd03b693735e Mon Sep 17 00:00:00 2001 From: Craig Tiller <craig.tiller@gmail.com> Date: Thu, 29 Jan 2015 17:19:45 -0800 Subject: [PATCH] Allow asynchronous call destruction in some cases If there's a chance we're being called via a callback, we need to delay destruction until later. Otherwise, for performance, destroy it inline. --- src/core/surface/call.c | 25 +++++++++++++++---------- src/core/surface/call.h | 2 +- src/core/surface/completion_queue.c | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 5e3f581509..8fb42e29be 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -183,8 +183,9 @@ legacy_state *get_legacy_state(grpc_call *call) { void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } -static void destroy_call(grpc_call *c) { +static void destroy_call(void *call, int ignored_success) { int i; + grpc_call *c = call; grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); gpr_mu_destroy(&c->mu); @@ -203,9 +204,13 @@ static void destroy_call(grpc_call *c) { gpr_free(c); } -void grpc_call_internal_unref(grpc_call *c) { +void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) { if (gpr_unref(&c->internal_refcount)) { - destroy_call(c); + if (allow_immediate_deletion) { + destroy_call(c, 1); + } else { + grpc_iomgr_add_callback(destroy_call, c); + } } } @@ -350,7 +355,7 @@ static void finish_write_step(void *pc, grpc_op_error error) { } call->sending = 0; unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); } static void finish_finish_step(void *pc, grpc_op_error error) { @@ -359,7 +364,7 @@ static void finish_finish_step(void *pc, grpc_op_error error) { finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, error); call->sending = 0; unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); } static void finish_start_step(void *pc, grpc_op_error error) { @@ -368,7 +373,7 @@ static void finish_start_step(void *pc, grpc_op_error error) { finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, error); call->sending = 0; unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); } static send_action choose_send_action(grpc_call *call) { @@ -464,7 +469,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { lock(call); call->sending = 0; unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); break; case SEND_FINISH: if (!call->is_client) { @@ -656,7 +661,7 @@ void grpc_call_destroy(grpc_call *c) { cancel = !c->stream_closed; unlock(c); if (cancel) grpc_call_cancel(c); - grpc_call_internal_unref(c); + grpc_call_internal_unref(c, 1); } grpc_call_error grpc_call_cancel(grpc_call *c) { @@ -958,7 +963,7 @@ static void call_alarm(void *arg, int success) { grpc_call_cancel(call); } } - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 1); } void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { @@ -998,7 +1003,7 @@ void grpc_call_stream_closed(grpc_call_element *elem) { finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); } unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); } /* we offset status by a small amount when storing it into transport metadata diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 57592089ee..c130a13b81 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -46,7 +46,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, const void *server_transport_data); void grpc_call_internal_ref(grpc_call *call); -void grpc_call_internal_unref(grpc_call *call); +void grpc_call_internal_unref(grpc_call *call, int allow_immediate_deletion); /* Helpers for grpc_client, grpc_server filters to publish received data to the completion queue/surface layer */ diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index 5854afbeef..ae3b96035c 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -388,7 +388,7 @@ void grpc_event_finish(grpc_event *base) { event *ev = (event *)base; ev->on_finish(ev->on_finish_user_data, GRPC_OP_OK); if (ev->base.call) { - grpc_call_internal_unref(ev->base.call); + grpc_call_internal_unref(ev->base.call, 1); } gpr_free(ev); } -- GitLab