Skip to content

Commit

Permalink
master: Issue 390: Clarify documentation of qb_loop_timer_expire_time…
Browse files Browse the repository at this point in the history
…_get and provide new function to return previously documented behavior (#391)

Includes unit test addition by chrissie-c
  • Loading branch information
cmurphycode authored Apr 29, 2020
1 parent 93f9975 commit 08806c5
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 2 deletions.
15 changes: 13 additions & 2 deletions include/qb/qbloop.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,16 +187,27 @@ int32_t qb_loop_timer_del(qb_loop_t *l, qb_loop_timer_handle th);
int32_t qb_loop_timer_is_running(qb_loop_t *l, qb_loop_timer_handle th);

/**
* Get the time remaining before it expires.
* Get the expiration time of the timer, as set when the timer was created
*
* @note if the timer has already expired it will return 0
*
* @param l pointer to the loop instance
* @param th timer handle.
* @return nano seconds left
* @return nano seconds at which the timer will expire
*/
uint64_t qb_loop_timer_expire_time_get(struct qb_loop *l, qb_loop_timer_handle th);

/**
* Get the time remaining before the timer expires
*
* @note if the timer has already expired it will return 0
*
* @param l pointer to the loop instance
* @param th timer handle.
* @return nano seconds remaining until the timer expires
*/
uint64_t qb_loop_timer_expire_time_remaining(struct qb_loop *l, qb_loop_timer_handle th);

/**
* Set a callback to receive events on file descriptors
* getting low.
Expand Down
50 changes: 50 additions & 0 deletions lib/loop_timerlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,56 @@ qb_loop_timer_expire_time_get(struct qb_loop * lp, qb_loop_timer_handle th)
return timerlist_expire_time(&s->timerlist, t->timerlist_handle);
}

uint64_t
qb_loop_timer_expire_time_remaining(struct qb_loop * lp, qb_loop_timer_handle th)
{

uint64_t current_ns;
/* NOTE: while it does not appear that absolute timers are used anywhere,
* we may as well respect this pattern in case that changes.
* Unfortunately, that means we do need to repeat timer fetch code from qb_loop_timer_expire_time_get
* rather than just a simple call to qb_loop_timer_expire_time_get and qb_util_nano_current_get.
*/

struct qb_timer_source *s;
struct qb_loop_timer *t;
int32_t res;
struct qb_loop *l = lp;

if (l == NULL) {
l = qb_loop_default_get();
}
s = (struct qb_timer_source *)l->timer_source;

res = _timer_from_handle_(s, th, &t);
if (res != 0) {
return 0;
}

struct timerlist_timer *timer = (struct timerlist_timer *)t->timerlist_handle;


if (timer->is_absolute_timer) {
current_ns = qb_util_nano_from_epoch_get();
}
else {
current_ns = qb_util_nano_current_get();
}
uint64_t timer_ns = timerlist_expire_time(&s->timerlist, t->timerlist_handle);
/* since time estimation is racy by nature, I'll try to check the state late,
* and try to understand that no matter what, the timer might have expired in the mean time
*/
if (t->state != QB_POLL_ENTRY_ACTIVE) {
return 0;
}
if (timer_ns < current_ns) {
return 0; // respect the "expired" contract
}
return timer_ns - current_ns;


}

int32_t
qb_loop_timer_is_running(qb_loop_t *l, qb_loop_timer_handle th)
{
Expand Down
19 changes: 19 additions & 0 deletions tests/check_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,22 @@ static Suite *loop_job_suite(void)
* Timers
*/
static qb_loop_timer_handle test_th;
static qb_loop_timer_handle test_th2;

static void check_time_left(void *data)
{
qb_loop_t *l = (qb_loop_t *)data;

/* NOTE: We are checking the 'stop_loop' timer here, not our own */
uint64_t abs_time = qb_loop_timer_expire_time_get(l, test_th);
uint64_t rel_time = qb_loop_timer_expire_time_remaining(l, test_th);

ck_assert(abs_time > 0ULL);
ck_assert(rel_time > 0ULL);
ck_assert(abs_time > rel_time);
ck_assert(rel_time <= 60*QB_TIME_NS_IN_MSEC);
}


START_TEST(test_loop_timer_input)
{
Expand Down Expand Up @@ -409,6 +425,9 @@ START_TEST(test_loop_timer_basic)
res = qb_loop_timer_add(l, QB_LOOP_LOW, 7*QB_TIME_NS_IN_MSEC, l, reset_one_shot_tmo, &reset_th);
ck_assert_int_eq(res, 0);

res = qb_loop_timer_add(l, QB_LOOP_HIGH, 20*QB_TIME_NS_IN_MSEC, l, check_time_left, &test_th2);
ck_assert_int_eq(res, 0);

res = qb_loop_timer_add(l, QB_LOOP_LOW, 60*QB_TIME_NS_IN_MSEC, l, job_stop, &test_th);
ck_assert_int_eq(res, 0);

Expand Down

0 comments on commit 08806c5

Please sign in to comment.