Better implementation, flip timer logic to make 0-init pre-triggered
diff --git a/src/core/lib/channel/deadline_filter.c b/src/core/lib/channel/deadline_filter.c
index fbc858b..8a8c3cb 100644
--- a/src/core/lib/channel/deadline_filter.c
+++ b/src/core/lib/channel/deadline_filter.c
@@ -73,45 +73,48 @@
     return;
   }
   grpc_deadline_state* deadline_state = elem->call_data;
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(deadline_state->timers); i++) {
-    if (gpr_atm_acq_load(&deadline_state->timers[i]) == 0) {
-      grpc_deadline_timer* timer = (i == 0 ? &deadline_state->inlined_timer
-                                           : gpr_malloc(sizeof(*timer)));
-      if (gpr_atm_rel_cas(&deadline_state->timers[i], 0, (gpr_atm)timer)) {
-        grpc_timer_init(
-            exec_ctx, &timer->timer, deadline,
-            grpc_closure_init(&timer->timer_callback, timer_callback, elem,
-                              grpc_schedule_on_exec_ctx),
-            gpr_now(GPR_CLOCK_MONOTONIC));
-      } else if (i != 0) {
-        gpr_free(timer);
+  grpc_deadline_timer_state cur_state;
+  grpc_closure* closure = NULL;
+retry:
+  cur_state =
+      (grpc_deadline_timer_state)gpr_atm_acq_load(&deadline_state->timer_state);
+  switch (cur_state) {
+    case GRPC_DEADLINE_STATE_PENDING:
+      return;
+    case GRPC_DEADLINE_STATE_FINISHED:
+      if (gpr_atm_rel_cas(&deadline_state->timer_state,
+                          GRPC_DEADLINE_STATE_FINISHED,
+                          GRPC_DEADLINE_STATE_PENDING)) {
+        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,
+                          GRPC_DEADLINE_STATE_PENDING)) {
+        closure =
+            grpc_closure_init(&deadline_state->timer_callback, timer_callback,
+                              elem, grpc_schedule_on_exec_ctx);
+      } else {
+        goto retry;
+      }
+      break;
   }
+  GPR_ASSERT(closure);
+  grpc_timer_init(exec_ctx, &deadline_state->timer, deadline, closure,
+                  gpr_now(GPR_CLOCK_MONOTONIC));
   GPR_UNREACHABLE_CODE(return;);
 }
 
 // Cancels the deadline timer.
 static void cancel_timer_if_needed(grpc_exec_ctx* exec_ctx,
                                    grpc_deadline_state* deadline_state) {
-  for (size_t i = 0; i < GPR_ARRAY_SIZE(deadline_state->timers); i++) {
-    gpr_atm timer_val;
-    timer_val = gpr_atm_acq_load(&deadline_state->timers[i]);
-    switch (timer_val) {
-      case 0:
-        return;
-      case TOMBSTONE_TIMER:
-        break;
-      default:
-        if (!gpr_atm_rel_cas(&deadline_state->timers[i], timer_val,
-                             TOMBSTONE_TIMER)) {
-          break;  // must have become a tombstone
-        }
-        grpc_deadline_timer* timer = (grpc_deadline_timer*)timer_val;
-        grpc_timer_cancel(exec_ctx, &timer->timer);
-        if (i != 0) gpr_free(timer);
-        break;
-    }
+  if (gpr_atm_acq_load(&deadline_state->timer_state) !=
+      GRPC_DEADLINE_STATE_INITIAL) {
+    grpc_timer_cancel(exec_ctx, &deadline_state->timer);
   }
 }
 
@@ -120,8 +123,8 @@
   grpc_deadline_state* deadline_state = arg;
   cancel_timer_if_needed(exec_ctx, deadline_state);
   // Invoke the next callback.
-  deadline_state->next_on_complete->cb(
-      exec_ctx, deadline_state->next_on_complete->cb_arg, error);
+  grpc_closure_run(exec_ctx, deadline_state->next_on_complete,
+                   GRPC_ERROR_REF(error));
 }
 
 // Inject our own on_complete callback into op.