Better cleanup

If the caller specifies a timeout, set it at call initialization
When we send initial metadata, take service config into account (iff
service config specifies a shorter deadline)

Saves a combiner on a critical path
pull/9906/head
Craig Tiller 8 years ago
parent a7ed26885c
commit 2c3d0a92c7
  1. 3
      src/core/ext/client_channel/client_channel.c
  2. 21
      src/core/lib/channel/deadline_filter.c
  3. 10
      src/core/lib/channel/deadline_filter.h

@ -740,7 +740,7 @@ static void apply_final_configuration_locked(grpc_exec_ctx *exec_ctx,
grpc_slice_hash_table_unref(exec_ctx, method_params_table);
}
/* Start deadline timer. */
grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
grpc_deadline_state_reset(exec_ctx, elem, calld->deadline);
}
static void subchannel_ready_locked(grpc_exec_ctx *exec_ctx, void *arg,
@ -1090,6 +1090,7 @@ static grpc_error *cc_init_call_elem(grpc_exec_ctx *exec_ctx,
calld->call_start_time = args->start_time;
calld->deadline = gpr_convert_clock_type(args->deadline, GPR_CLOCK_MONOTONIC);
calld->owning_call = args->call_stack;
grpc_deadline_state_start(exec_ctx, elem, calld->deadline);
return GRPC_ERROR_NONE;
}

@ -78,9 +78,21 @@ retry:
(grpc_deadline_timer_state)gpr_atm_acq_load(&deadline_state->timer_state);
switch (cur_state) {
case GRPC_DEADLINE_STATE_PENDING:
case GRPC_DEADLINE_STATE_FINISHED:
// Note: We do not start the timer if there is already a timer
return;
case GRPC_DEADLINE_STATE_FINISHED:
if (gpr_atm_rel_cas(&deadline_state->timer_state,
GRPC_DEADLINE_STATE_FINISHED,
GRPC_DEADLINE_STATE_PENDING)) {
// If we've already created and destroyed a timer, we always create a
// new closure: we have no other guarantee that the inlined closure is
// not in use (it may hold a pending call to timer_callback)
closure = grpc_closure_create(timer_callback, elem,
grpc_schedule_on_exec_ctx);
} else {
goto retry;
}
break;
case GRPC_DEADLINE_STATE_INITIAL:
if (gpr_atm_rel_cas(&deadline_state->timer_state,
GRPC_DEADLINE_STATE_INITIAL,
@ -177,6 +189,13 @@ void grpc_deadline_state_start(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
}
}
void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
gpr_timespec new_deadline) {
grpc_deadline_state* deadline_state = elem->call_data;
cancel_timer_if_needed(exec_ctx, deadline_state);
start_timer_if_needed(exec_ctx, elem, new_deadline);
}
void grpc_deadline_state_client_start_transport_stream_op(
grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
grpc_transport_stream_op* op) {

@ -73,6 +73,16 @@ void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
void grpc_deadline_state_start(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
gpr_timespec deadline);
// Cancels the existing timer and starts a new one with new_deadline.
//
// Note: It is generally safe to call this with an earlier deadline
// value than the current one, but not the reverse. No checks are done
// to ensure that the timer callback is not invoked while it is in the
// process of being reset, which means that attempting to increase the
// deadline may result in the timer being called twice.
void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
gpr_timespec new_deadline);
// To be called from the client-side filter's start_transport_stream_op()
// method. Ensures that the deadline timer is cancelled when the call
// is completed.

Loading…
Cancel
Save