Merge pull request #6901 from kivaisan/eventqueue_time_left

events: Introduce API to query how much time is left for delayed event
pull/6869/merge
Cruz Monrreal 2018-05-21 10:12:13 -05:00 committed by GitHub
commit 86d04d7b15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 0 deletions

View File

@ -250,6 +250,46 @@ void event_inference_test() {
TEST_ASSERT_EQUAL(counter, 60);
}
int timeleft_events[2];
void check_time_left(EventQueue* queue, int index, int expected) {
const int event_id = timeleft_events[index];
TEST_ASSERT_INT_WITHIN(2, expected, queue->time_left(event_id));
touched = true;
}
void time_left(EventQueue* queue, int index) {
const int event_id = timeleft_events[index];
TEST_ASSERT_EQUAL(0, queue->time_left(event_id));
}
void time_left_test() {
EventQueue queue(TEST_EQUEUE_SIZE);
// Enque check events
TEST_ASSERT(queue.call_in(50, check_time_left, &queue, 0, 100-50));
TEST_ASSERT(queue.call_in(200, check_time_left, &queue, 1, 200-200));
// Enque events to be checked
timeleft_events[0] = queue.call_in(100, time_left, &queue, 0);
timeleft_events[1] = queue.call_in(200, time_left, &queue, 1);
TEST_ASSERT(timeleft_events[0]);
TEST_ASSERT(timeleft_events[1]);
queue.dispatch(300);
// Ensure check was called
TEST_ASSERT(touched);
touched = false;
int id = queue.call(func0);
TEST_ASSERT(id);
TEST_ASSERT_EQUAL(0, queue.time_left(id));
queue.dispatch(10);
// Test invalid event id
TEST_ASSERT_EQUAL(-1, queue.time_left(0));
}
// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) {
@ -274,6 +314,8 @@ const Case cases[] = {
Case("Testing the event class", event_class_test),
Case("Testing the event class helpers", event_class_helper_test),
Case("Testing the event inference", event_inference_test),
Case("Testing time_left", time_left_test),
};
Specification specification(test_setup, cases);

View File

@ -47,6 +47,10 @@ void EventQueue::cancel(int id) {
return equeue_cancel(&_equeue, id);
}
int EventQueue::time_left(int id) {
return equeue_timeleft(&_equeue, id);
}
void EventQueue::background(Callback<void(int)> update) {
_update = update;

View File

@ -114,6 +114,8 @@ public:
* one of the call functions. It is safe to call cancel after an event
* has already been dispatched.
*
* id must be valid i.e. event must have not finished executing.
*
* The cancel function is irq safe.
*
* If called while the event queue's dispatch loop is active, the cancel
@ -124,6 +126,25 @@ public:
*/
void cancel(int id);
/** Query how much time is left for delayed event
*
* If the event is delayed, this function can be used to query how much time
* is left until the event is due to be dispatched.
*
* id must be valid i.e. event must have not finished executing.
*
* This function is irq safe.
*
* @param id Unique id of the event
*
* @return Remaining time in milliseconds or
* 0 if event is already due to be dispatched or
* is currently executing.
* Undefined if id is invalid.
*
*/
int time_left(int id);
/** Background an event queue onto a single-shot timer-interrupt
*
* When updated, the event queue will call the provided update function
@ -171,6 +192,8 @@ public:
* @return A unique id that represents the posted event and can
* be passed to cancel, or an id of 0 if there is not
* enough memory to allocate the event.
* Returned id will remain valid until event has finished
* executing.
*/
template <typename F>
int call(F f) {

View File

@ -364,6 +364,25 @@ void equeue_cancel(equeue_t *q, int id) {
}
}
int equeue_timeleft(equeue_t *q, int id) {
int ret = -1;
if (!id) {
return -1;
}
// decode event from unique id and check that the local id matches
struct equeue_event *e = (struct equeue_event *)
&q->buffer[id & ((1 << q->npw2)-1)];
equeue_mutex_lock(&q->queuelock);
if (e->id == id >> q->npw2) {
ret = equeue_clampdiff(e->target, equeue_tick());
}
equeue_mutex_unlock(&q->queuelock);
return ret;
}
void equeue_break(equeue_t *q) {
equeue_mutex_lock(&q->queuelock);
q->break_requested = true;

View File

@ -187,6 +187,15 @@ int equeue_post(equeue_t *queue, void (*cb)(void *), void *event);
// the event may have already begun executing.
void equeue_cancel(equeue_t *queue, int id);
// Query how much time is left for delayed event
//
// If event is delayed, this function can be used to query how much time
// is left until the event is due to be dispatched.
//
// This function is irq safe.
//
int equeue_timeleft(equeue_t *q, int id);
// Background an event queue onto a single-shot timer
//
// The provided update function will be called to indicate when the queue