mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #14087 from adbridge/events
Update events period method to check for invalid valuespull/14173/head
						commit
						97c7c91655
					
				| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
#include <utility>
 | 
			
		||||
#include "events/EventQueue.h"
 | 
			
		||||
#include "platform/mbed_assert.h"
 | 
			
		||||
#include "platform/mbed_error.h"
 | 
			
		||||
 | 
			
		||||
namespace events {
 | 
			
		||||
/** \defgroup events-public-api Events
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +28,8 @@ namespace events {
 | 
			
		|||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static constexpr std::chrono::duration<int, std::milli> non_periodic{-1};
 | 
			
		||||
 | 
			
		||||
/** Event
 | 
			
		||||
 *
 | 
			
		||||
 *  Representation of an event for fine-grain dispatch control
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +70,7 @@ public:
 | 
			
		|||
            _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>;
 | 
			
		||||
| 
						 | 
				
			
			@ -139,13 +142,24 @@ public:
 | 
			
		|||
 | 
			
		||||
    /** 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;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);                                   \
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			@ -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--) {
 | 
			
		||||
| 
						 | 
				
			
			@ -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]);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue