struct isc_timer {
unsigned int magic;
- isc_refcount_t references;
isc_loop_t *loop;
uv_timer_t timer;
isc_job_cb cb;
void *cbarg;
-
- /*
- * We are locking the values here for now, but this needs to go away
- * when the timers are pinned to the respective loops.
- */
- isc_mutex_t lock;
uint64_t timeout;
uint64_t repeat;
+ atomic_bool running;
};
-static void
-isc__timer_detach(isc_timer_t **timerp);
-
void
isc_timer_create(isc_loop_t *loop, isc_job_cb cb, void *cbarg,
isc_timer_t **timerp) {
REQUIRE(VALID_LOOPMGR(loopmgr));
- REQUIRE(loop == isc_loop_current(loopmgr) ||
- !atomic_load(&loopmgr->running) ||
- atomic_load(&loopmgr->paused) > 0);
+ REQUIRE(loop == isc_loop_current(loopmgr));
timer = isc_mem_get(loop->mctx, sizeof(*timer));
*timer = (isc_timer_t){
.cb = cb,
.cbarg = cbarg,
+ .magic = TIMER_MAGIC,
};
isc_loop_attach(loop, &timer->loop);
- isc_refcount_init(&timer->references, 1);
-
- isc_mutex_init(&timer->lock);
-
- timer->magic = TIMER_MAGIC;
-
- r = uv_timer_init(&timer->loop->loop, &timer->timer);
+ r = uv_timer_init(&loop->loop, &timer->timer);
UV_RUNTIME_CHECK(uv_timer_init, r);
uv_handle_set_data(&timer->timer, timer);
*timerp = timer;
}
-static void
-isc__timer_stop(void *arg) {
- isc_timer_t *timer = (isc_timer_t *)arg;
- uv_timer_stop(&timer->timer);
- isc__timer_detach(&timer);
-}
-
void
isc_timer_stop(isc_timer_t *timer) {
REQUIRE(VALID_TIMER(timer));
- isc_refcount_increment(&timer->references);
+ if (!atomic_compare_exchange_strong_acq_rel(&timer->running,
+ &(bool){ true }, false))
+ {
+ /* Timer was already stopped */
+ return;
+ }
+
+ /* Stop the timer, if the loops are matching */
if (timer->loop == isc_loop_current(timer->loop->loopmgr)) {
- isc__timer_stop(timer);
- } else {
- isc_async_run(timer->loop, isc__timer_stop, timer);
+ uv_timer_stop(&timer->timer);
}
}
REQUIRE(VALID_TIMER(timer));
- timer->cb(timer->cbarg);
-}
-
-static void
-isc__timer_start(void *arg) {
- isc_timer_t *timer = (isc_timer_t *)arg;
-
- LOCK(&timer->lock);
- int r = uv_timer_start(&timer->timer, timer_cb, timer->timeout,
- timer->repeat);
- UV_RUNTIME_CHECK(uv_timer_start, r);
- UNLOCK(&timer->lock);
+ if (!atomic_load_acquire(&timer->running)) {
+ uv_timer_stop(&timer->timer);
+ return;
+ }
- isc__timer_detach(&timer);
+ timer->cb(timer->cbarg);
}
void
const isc_interval_t *interval) {
isc_loopmgr_t *loopmgr = NULL;
isc_loop_t *loop = NULL;
+ int r;
REQUIRE(VALID_TIMER(timer));
REQUIRE(type == isc_timertype_ticker || type == isc_timertype_once);
+ REQUIRE(timer->loop == isc_loop_current(timer->loop->loopmgr));
loop = timer->loop;
REQUIRE(VALID_LOOPMGR(loopmgr));
- LOCK(&timer->lock);
switch (type) {
case isc_timertype_once:
timer->timeout = isc_interval_ms(interval);
default:
UNREACHABLE();
}
- UNLOCK(&timer->lock);
- isc_refcount_increment(&timer->references);
- if (timer->loop == isc_loop_current(timer->loop->loopmgr)) {
- isc__timer_start(timer);
- } else {
- isc_async_run(timer->loop, isc__timer_start, timer);
- }
+ atomic_store_release(&timer->running, true);
+ r = uv_timer_start(&timer->timer, timer_cb, timer->timeout,
+ timer->repeat);
+ UV_RUNTIME_CHECK(uv_timer_start, r);
}
static void
-timer_destroy(uv_handle_t *handle) {
+timer_close(uv_handle_t *handle) {
isc_timer_t *timer = uv_handle_get_data(handle);
isc_loop_t *loop;
loop = timer->loop;
- isc_refcount_destroy(&timer->references);
- isc_mutex_destroy(&timer->lock);
-
isc_mem_put(loop->mctx, timer, sizeof(*timer));
isc_loop_detach(&loop);
}
static void
-isc__timer_destroy(void *arg) {
- isc_timer_t *timer = (isc_timer_t *)arg;
+timer_destroy(void *arg) {
+ isc_timer_t *timer = arg;
+ atomic_store_release(&timer->running, false);
uv_timer_stop(&timer->timer);
- uv_close(&timer->timer, timer_destroy);
+ uv_close(&timer->timer, timer_close);
}
-static void
-isc__timer_detach(isc_timer_t **timerp) {
+void
+isc_timer_destroy(isc_timer_t **timerp) {
isc_timer_t *timer = NULL;
REQUIRE(timerp != NULL && VALID_TIMER(*timerp));
timer = *timerp;
*timerp = NULL;
- if (isc_refcount_decrement(&timer->references) == 1) {
- if (timer->loop == isc_loop_current(timer->loop->loopmgr)) {
- isc__timer_destroy(timer);
- } else {
- isc_async_run(timer->loop, isc__timer_destroy, timer);
- }
- }
-}
+ REQUIRE(timer->loop == isc_loop_current(timer->loop->loopmgr));
-void
-isc_timer_destroy(isc_timer_t **timerp) {
- isc__timer_detach(timerp);
+ timer_destroy(timer);
}
void
*timerp = NULL;
isc_timer_stop(timer);
- isc_async_run(timer->loop, isc__timer_destroy, timer);
+ isc_async_run(timer->loop, timer_destroy, timer);
}