Skip to content

Commit

Permalink
Merge pull request ARMmbed#14087 from adbridge/events
Browse files Browse the repository at this point in the history
Update events period method to check for invalid values
  • Loading branch information
0xc0170 authored Jan 18, 2021
2 parents dde7b22 + 81d7ac6 commit 97c7c91
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 18 deletions.
20 changes: 17 additions & 3 deletions events/include/events/Event.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
#include <utility>
#include "events/EventQueue.h"
#include "platform/mbed_assert.h"
#include "platform/mbed_error.h"

namespace events {
/** \defgroup events-public-api Events
* \ingroup mbed-os-public
* @{
*/

static constexpr std::chrono::duration<int, std::milli> non_periodic{-1};

/** Event
*
* Representation of an event for fine-grain dispatch control
Expand Down Expand Up @@ -67,7 +70,7 @@ class Event<void(ArgTs...)> {
_event->equeue = &q->_equeue;
_event->id = 0;
_event->delay = duration(0);
_event->period = duration(-1);
_event->period = non_periodic;

_event->post = &Event::event_post<F>;
_event->dtor = &Event::event_dtor<F>;
Expand Down Expand Up @@ -139,13 +142,24 @@ class Event<void(ArgTs...)> {

/** Configure the period of an event
*
* @param p Period (in milliseconds) for repeatedly dispatching an event, expressed as a Chrono duration.
* @param p Period (in milliseconds) for repeatedly dispatching an event, expressed as a Chrono
* duration. Period must be either non_periodic or > 0ms. If an invalid period is supplied
* then a default non_periodic value is used.
* E.g. period(200ms)
*/
void period(duration p)
{
if (_event) {
_event->period = p;
if (p > duration(0)) {
_event->period = p;

} else {
if (p != non_periodic) {
MBED_WARNING(MBED_ERROR_INVALID_ARGUMENT,
"Invalid period specified, defaulting to non_periodic.");
}
_event->period = non_periodic;
}
}
}

Expand Down
113 changes: 98 additions & 15 deletions events/tests/TESTS/events/queue/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,12 @@ void simple_posts_test##i() { \
TEST_ASSERT(touched); \
\
touched = false; \
queue.call_in(1, func##i,##__VA_ARGS__); \
queue.call_in(1ms, func##i,##__VA_ARGS__); \
queue.dispatch(2); \
TEST_ASSERT(touched); \
\
touched = false; \
queue.call_every(1, func##i,##__VA_ARGS__); \
queue.call_every(1ms, func##i,##__VA_ARGS__); \
queue.dispatch(2); \
TEST_ASSERT(touched); \
}
Expand Down Expand Up @@ -126,7 +126,7 @@ void call_in_test()

for (int i = 0; i < N; i++) {
tickers[i].start();
queue.call_in((i + 1) * 100, time_func, &tickers[i], (i + 1) * 100);
queue.call_in((i + 1) * 100ms, time_func, &tickers[i], (i + 1) * 100);
}

queue.dispatch(N * 100);
Expand All @@ -141,7 +141,7 @@ void call_every_test()

for (int i = 0; i < N; i++) {
tickers[i].start();
queue.call_every((i + 1) * 100, time_func, &tickers[i], (i + 1) * 100);
queue.call_every((i + 1) * 100ms, time_func, &tickers[i], (i + 1) * 100);
}

queue.dispatch(N * 100);
Expand Down Expand Up @@ -172,7 +172,7 @@ void cancel_test1()
int ids[N];

for (int i = 0; i < N; i++) {
ids[i] = queue.call_in(1000, no);
ids[i] = queue.call_in(1000ms, no);
}

for (int i = N - 1; i >= 0; i--) {
Expand Down Expand Up @@ -308,12 +308,12 @@ 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));
TEST_ASSERT(queue.call_in(50ms, check_time_left, &queue, 0, 100 - 50));
TEST_ASSERT(queue.call_in(200ms, 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);
timeleft_events[0] = queue.call_in(100ms, time_left, &queue, 0);
timeleft_events[1] = queue.call_in(200ms, time_left, &queue, 1);
TEST_ASSERT(timeleft_events[0]);
TEST_ASSERT(timeleft_events[1]);

Expand Down Expand Up @@ -373,18 +373,18 @@ void mixed_dynamic_static_events_queue_test()

EventTest e1_test;
Event<void()> e1 = queue.event(&e1_test, &EventTest::f0);
e1.delay(10);
e1.period(10);
e1.delay(10ms);
e1.period(10ms);
int id1 = e1.post();
TEST_ASSERT_NOT_EQUAL(0, id1);
EventTest e2_test;
Event<void()> e2 = queue.event(&e2_test, &EventTest::f1, 3);
e2.period(10);
e2.period(10ms);
int id2 = e2.post();
TEST_ASSERT_NOT_EQUAL(0, id2);
EventTest e3_test;
Event<void()> e3 = queue.event(&e3_test, &EventTest::f5, 1, 2, 3, 4, 5);
e3.period(10);
e3.period(10ms);
int id3 = e3.post();
TEST_ASSERT_NOT_EQUAL(0, id3);

Expand Down Expand Up @@ -508,6 +508,89 @@ void static_events_queue_test()
TEST_ASSERT_EQUAL(15, test4.counter);
}

static EventQueue period_tests_queue;
static long update_counter = 0;

void handler()
{
update_counter ++;
}

void event_period_tests()
{
// Test a non periodic event ie dispatched only once

Event<void()> event1(&period_tests_queue, handler);

event1.delay(10ms);
event1.period(events::non_periodic);
event1.post();
period_tests_queue.dispatch(80);

// Wait 100ms and check the event execution status
wait_us(100 * 1000);

// Event should only have been dispatched once and thus counter
// should be 1
TEST_ASSERT_EQUAL(1, update_counter);

// Test an event with an invalid negative period value.

update_counter = 0;

Event<void()> event2(&period_tests_queue, handler);

event2.delay(10ms);
event2.period(-10ms);
event2.post();
period_tests_queue.dispatch(80);

// Wait 100ms and check the event execution status
wait_us(100 * 1000);

// Event should default to non_periodic and thus only have been
// dispatched once. Counter should be 1.
TEST_ASSERT_EQUAL(1, update_counter);

// Test an event with a zero period.

update_counter = 0;

Event<void()> event3(&period_tests_queue, handler);

event3.delay(10ms);
event3.period(0ms);
event3.post();
period_tests_queue.dispatch(80);

// Wait 100ms and check the event execution status
wait_us(100 * 1000);

// Event should default to non_periodic and thus only have been
// dispatched once. Counter should be 1.
TEST_ASSERT_EQUAL(1, update_counter);

// Test a periodic event ie dispatched a number of times
update_counter = 0;

Event<void()> event4(&period_tests_queue, handler);

event4.delay(10ms);
event4.period(20ms);
event4.post();
period_tests_queue.dispatch(80);

// Wait 100ms and check the event execution status
wait_us(100 * 1000);

// The event should be first dispatched after 10ms and then
// every subsequent 20ms until the dispatcher has completed.
// Thus the counter should be incremented after :
// 10ms, 30ms, 50ms and 70ms
TEST_ASSERT_EQUAL(4, update_counter);

}

// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases)
{
Expand Down Expand Up @@ -535,8 +618,8 @@ const Case cases[] = {

Case("Testing time_left", time_left_test),
Case("Testing mixed dynamic & static events queue", mixed_dynamic_static_events_queue_test),
Case("Testing static events queue", static_events_queue_test)

Case("Testing static events queue", static_events_queue_test),
Case("Testing event period values", event_period_tests)
};

Specification specification(test_setup, cases);
Expand Down

0 comments on commit 97c7c91

Please sign in to comment.