Esempio n. 1
0
/**
 * 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);
}
Esempio n. 2
0
/**
 * 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);
}
Esempio n. 3
0
void rd_kafka_timers_destroy (rd_kafka_timers_t *rkts) {
        rd_kafka_timer_t *rtmr;

        rd_kafka_timers_lock(rkts);
        rkts->rkts_enabled = 0;
        while ((rtmr = TAILQ_FIRST(&rkts->rkts_timers)))
                rd_kafka_timer_stop(rkts, rtmr, 0);
        rd_kafka_assert(rkts->rkts_rk, TAILQ_EMPTY(&rkts->rkts_timers));
        rd_kafka_timers_unlock(rkts);

        cnd_destroy(&rkts->rkts_cond);
        mtx_destroy(&rkts->rkts_lock);
}
Esempio n. 4
0
/**
 * Start the provided timer with the given interval.
 * Upon expiration of the interval (us) the callback will be called in the
 * main rdkafka thread, after callback return the timer will be restarted.
 *
 * Use rd_kafka_timer_stop() to stop a timer.
 */
void rd_kafka_timer_start (rd_kafka_timers_t *rkts,
			   rd_kafka_timer_t *rtmr, int interval,
			   void (*callback) (rd_kafka_timers_t *rkts, void *arg),
			   void *arg) {
	rd_kafka_timers_lock(rkts);

	rd_kafka_timer_stop(rkts, rtmr, 0/*!lock*/);

	rtmr->rtmr_interval = interval;
	rtmr->rtmr_callback = callback;
	rtmr->rtmr_arg      = arg;

	rd_kafka_timer_schedule(rkts, rtmr, 0);

	rd_kafka_timers_unlock(rkts);
}
Esempio n. 5
0
/**
 * 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);
}
Esempio n. 6
0
/**
 * @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;
}
Esempio n. 7
0
/**
 * Returns the delta time to the next timer to fire, capped by 'timeout_ms'.
 */
rd_ts_t rd_kafka_timers_next (rd_kafka_timers_t *rkts, int timeout_us,
			      int do_lock) {
	rd_ts_t now = rd_clock();
	rd_ts_t sleeptime = 0;
	rd_kafka_timer_t *rtmr;

	if (do_lock)
		rd_kafka_timers_lock(rkts);

	if (likely((rtmr = TAILQ_FIRST(&rkts->rkts_timers)) != NULL)) {
		sleeptime = rtmr->rtmr_next - now;
		if (sleeptime < 0)
			sleeptime = 0;
		else if (sleeptime > (rd_ts_t)timeout_us)
			sleeptime = (rd_ts_t)timeout_us;
	} else
		sleeptime = (rd_ts_t)timeout_us;

	if (do_lock)
		rd_kafka_timers_unlock(rkts);

	return sleeptime;
}
Esempio n. 8
0
/**
 * Interrupt rd_kafka_timers_run().
 * Used for termination.
 */
void rd_kafka_timers_interrupt (rd_kafka_timers_t *rkts) {
	rd_kafka_timers_lock(rkts);
	cnd_signal(&rkts->rkts_cond);
	rd_kafka_timers_unlock(rkts);
}