Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

master: Issue 390: Clarify documentation of qb_loop_timer_expire_time… #391

Merged
merged 1 commit into from
Apr 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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