/** * Delay the next timer invocation by 'backoff_us' */ void rd_kafka_timer_backoff (rd_kafka_timers_t *rkts, rd_kafka_timer_t *rtmr, int backoff_us) { rd_kafka_timers_lock(rkts); if (rd_kafka_timer_scheduled(rtmr)) rd_kafka_timer_unschedule(rkts, rtmr); rd_kafka_timer_schedule(rkts, rtmr, backoff_us); rd_kafka_timers_unlock(rkts); }
/** * Dispatch timers. * Will block up to 'timeout' microseconds before returning. */ void rd_kafka_timers_run (rd_kafka_timers_t *rkts, int timeout_us) { rd_ts_t now = rd_clock(); rd_ts_t end = now + timeout_us; rd_kafka_timers_lock(rkts); while (!rd_atomic32_get(&rkts->rkts_rk->rk_terminate) && now <= end) { int64_t sleeptime; rd_kafka_timer_t *rtmr; if (timeout_us != RD_POLL_NOWAIT) { sleeptime = rd_kafka_timers_next(rkts, timeout_us, 0/*no-lock*/); if (sleeptime > 0) { cnd_timedwait_ms(&rkts->rkts_cond, &rkts->rkts_lock, (int)(sleeptime / 1000)); } } now = rd_clock(); while ((rtmr = TAILQ_FIRST(&rkts->rkts_timers)) && rtmr->rtmr_next <= now) { rd_kafka_timer_unschedule(rkts, rtmr); rd_kafka_timers_unlock(rkts); rtmr->rtmr_callback(rkts, rtmr->rtmr_arg); rd_kafka_timers_lock(rkts); /* Restart timer, unless it has been stopped, or * already reschedueld (start()ed) from callback. */ if (rd_kafka_timer_started(rtmr) && !rd_kafka_timer_scheduled(rtmr)) rd_kafka_timer_schedule(rkts, rtmr, 0); } if (timeout_us == RD_POLL_NOWAIT) { /* Only iterate once, even if rd_clock doesn't change */ break; } } rd_kafka_timers_unlock(rkts); }
/** * Stop a timer that may be started. * If called from inside a timer callback 'lock' must be 0, else 1. */ void rd_kafka_timer_stop (rd_kafka_timers_t *rkts, rd_kafka_timer_t *rtmr, int lock) { if (lock) rd_kafka_timers_lock(rkts); if (!rd_kafka_timer_started(rtmr)) { if (lock) rd_kafka_timers_unlock(rkts); return; } if (rd_kafka_timer_scheduled(rtmr)) rd_kafka_timer_unschedule(rkts, rtmr); rtmr->rtmr_interval = 0; if (lock) rd_kafka_timers_unlock(rkts); }
/** * @returns the delta time to the next time (>=0) this timer fires, or -1 * if timer is stopped. */ rd_ts_t rd_kafka_timer_next (rd_kafka_timers_t *rkts, rd_kafka_timer_t *rtmr, int do_lock) { rd_ts_t now = rd_clock(); rd_ts_t delta = -1; if (do_lock) rd_kafka_timers_lock(rkts); if (rd_kafka_timer_scheduled(rtmr)) { delta = rtmr->rtmr_next - now; if (delta < 0) delta = 0; } if (do_lock) rd_kafka_timers_unlock(rkts); return delta; }