diff --git a/include/etl/callback_timer_deferred_locked.h b/include/etl/callback_timer_deferred_locked.h index e9679bc7..d0a46e89 100644 --- a/include/etl/callback_timer_deferred_locked.h +++ b/include/etl/callback_timer_deferred_locked.h @@ -97,7 +97,6 @@ namespace etl count -= timer.delta; active_list.remove(timer.id, true); - remove_callback.call_if(timer.id); if (timer.callback.is_valid()) { @@ -112,9 +111,10 @@ namespace etl // Reinsert the timer. timer.delta = timer.period; active_list.insert(timer.id); - insert_callback.call_if(timer.id); } + time_to_next_callback.call_if(time_to_next()); + has_active = !active_list.empty(); } diff --git a/include/etl/callback_timer_locked.h b/include/etl/callback_timer_locked.h index 5579ec0b..39f5bde0 100644 --- a/include/etl/callback_timer_locked.h +++ b/include/etl/callback_timer_locked.h @@ -53,7 +53,7 @@ namespace etl typedef etl::delegate lock_type; typedef etl::delegate unlock_type; - typedef etl::delegate event_callback_type; + typedef etl::delegate event_callback_type; //******************************************* /// Register a timer. @@ -102,7 +102,7 @@ namespace etl { lock(); active_list.remove(timer.id, false); - remove_callback.call_if(timer.id); + time_to_next_callback.call_if(time_to_next()); unlock(); } @@ -180,12 +180,11 @@ namespace etl if (timer.is_active()) { active_list.remove(timer.id, false); - remove_callback.call_if(timer.id); } timer.delta = immediate_ ? 0U : timer.period; active_list.insert(timer.id); - insert_callback.call_if(timer.id); + time_to_next_callback.call_if(time_to_next()); unlock(); result = true; @@ -215,7 +214,7 @@ namespace etl { lock(); active_list.remove(timer.id, false); - remove_callback.call_if(timer.id); + time_to_next_callback.call_if(time_to_next()); unlock(); } @@ -324,31 +323,17 @@ namespace etl } //******************************************* - /// Set a callback when a timer is inserted on list + /// Set a callback when the time to the next timer changes //******************************************* - void set_insert_callback(event_callback_type insert_) + void set_time_to_next_callback(event_callback_type callback_) { - insert_callback = insert_; + time_to_next_callback = callback_; } //******************************************* - /// Set a callback when a timer is removed from list - //******************************************* - void set_remove_callback(event_callback_type remove_) + void clear_time_to_next_callback() { - remove_callback = remove_; - } - - //******************************************* - void clear_insert_callback() - { - insert_callback.clear(); - } - - //******************************************* - void clear_remove_callback() - { - remove_callback.clear(); + time_to_next_callback.clear(); } protected: @@ -641,8 +626,7 @@ namespace etl lock_type lock; ///< The callback that locks. unlock_type unlock; ///< The callback that unlocks. - event_callback_type insert_callback; - event_callback_type remove_callback; + event_callback_type time_to_next_callback; public: @@ -714,7 +698,6 @@ namespace etl count -= timer.delta; active_list.remove(timer.id, true); - remove_callback.call_if(timer.id); if (timer.callback.is_valid()) { @@ -726,9 +709,10 @@ namespace etl // Reinsert the timer. timer.delta = timer.period; active_list.insert(timer.id); - insert_callback.call_if(timer.id); } + time_to_next_callback.call_if(time_to_next()); + has_active = !active_list.empty(); } diff --git a/test/test_callback_timer_deferred_locked.cpp b/test/test_callback_timer_deferred_locked.cpp index 9ab130ea..6c0508d3 100644 --- a/test/test_callback_timer_deferred_locked.cpp +++ b/test/test_callback_timer_deferred_locked.cpp @@ -156,38 +156,29 @@ namespace callback_type member_callback_inc2 = callback_type::create(); callback_type member_callback_inc3 = callback_type::create(); - class TimerInsertRemoveTest + class TimerTimeToNextTest { public: - uint32_t inserted; - uint32_t removed; - TimerInsertRemoveTest() - : inserted(0) - , removed(0) + uint32_t time_to_next; + + TimerTimeToNextTest() + : time_to_next(0) { } - void insert_handler(etl::timer::id::type id_) + void time_to_next_handler(uint32_t time_to_next_) { - (void)id_; - inserted++; - } - - void remove_handler(etl::timer::id::type id_) - { - (void)id_; - removed++; + time_to_next = time_to_next_; } void clear(void) { - inserted = 0; - removed = 0; + time_to_next = 0; } }; - TimerInsertRemoveTest timerInsertRemoveTest; + TimerTimeToNextTest timerTimeToNextTest; //*************************************************************************** // Free function callback via etl::function @@ -1013,9 +1004,49 @@ namespace } //************************************************************************* - TEST(callback_timer_is_active) + // Tick ID1 ID2 ID3 + // 0 . . . + // 1 . . . + // 2 . . . + // 3 . . . + // 4 . . . + // 5 . . . + // 6 . . . + // 7 . . . + // 8 . . . + // 9 . . O + // 10 . . . + // 11 . . . + // 12 . . . + // 13 . . . + // 14 . . . + // 15 . . . + // 16 . . . + // 17 . . . + // 18 . . O + // 19 . . . + // 20 . . . + // 21 . . . + // 22 . . . + // 23 . O . + // 24 . . . + // 25 . . . + // 26 . . . + // 27 . . O + // 28 . . . + // 29 . . . + // 30 . . . + // 31 . . . + // 32 . . . + // 33 . . . + // 34 . . . + // 35 . . . + // 36 . . O + // 37 O . . + // + TEST(callback_timer_is_active_and_time_to_next) { - timerInsertRemoveTest.clear(); + timerTimeToNextTest.clear(); locks.clear(); try_lock_type try_lock = try_lock_type::create(); lock_type lock = lock_type::create(); @@ -1025,19 +1056,20 @@ namespace etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Single_Shot); etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot); - etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 11, etl::timer::mode::Single_Shot); + etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 9, etl::timer::mode::Repeating); - timer_controller.set_insert_callback( - event_callback_type::create()); - timer_controller.set_remove_callback( - event_callback_type::create()); + timer_controller.set_time_to_next_callback( + event_callback_type::create()); timer_controller.start(id1); timer_controller.start(id3); timer_controller.start(id2); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(0, timerInsertRemoveTest.removed); + timer_controller.start(id1); + timer_controller.start(id3); + timer_controller.start(id2); + + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); // The time to next should be the interval for id3. timer_controller.enable(true); @@ -1045,81 +1077,77 @@ namespace CHECK_TRUE(timer_controller.is_active(id2)); CHECK_TRUE(timer_controller.is_active(id3)); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(0, timerInsertRemoveTest.removed); + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); // The time to next should be the interval for id3. - timer_controller.tick(11); + // Tick the time for id3 to expire. + timer_controller.tick(9); timer_controller.handle_deferred(); CHECK_TRUE(timer_controller.is_active(id1)); CHECK_TRUE(timer_controller.is_active(id2)); - CHECK_FALSE(timer_controller.is_active(id3)); + CHECK_TRUE(timer_controller.is_active(id3)); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(1, timerInsertRemoveTest.removed); + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); // The time to next should be the what's left of the interval for id3. - timer_controller.tick(23 - 11); + // Stop the timer and check that the time to next is updated to that of id2. + timer_controller.stop(id3); + CHECK_EQUAL(14, timerTimeToNextTest.time_to_next); // The time to next should be the what's left of the interval for id2. + + // Start the timer again and check that the time to next is updated to the interval for id3. + timer_controller.start(id3); + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); + + // Tick the time for id3 to expire. + timer_controller.tick(9); + timer_controller.handle_deferred(); + CHECK_TRUE(timer_controller.is_active(id1)); + CHECK_TRUE(timer_controller.is_active(id2)); + CHECK_TRUE(timer_controller.is_active(id3)); + + // The time to next should be the what's left of the interval for id2. + CHECK_EQUAL(5, timerTimeToNextTest.time_to_next); + + // Tick the remaining time for id2 to expire. + timer_controller.tick(5); timer_controller.handle_deferred(); CHECK_TRUE(timer_controller.is_active(id1)); CHECK_FALSE(timer_controller.is_active(id2)); - CHECK_FALSE(timer_controller.is_active(id3)); + CHECK_TRUE(timer_controller.is_active(id3)); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(2, timerInsertRemoveTest.removed); + // The time to next should be the what's left of the interval for id3. + CHECK_EQUAL(4, timerTimeToNextTest.time_to_next); - timer_controller.tick(37 - 23); + // Tick the remaining time for id3 to expire. + timer_controller.tick(4); + timer_controller.handle_deferred(); + CHECK_TRUE(timer_controller.is_active(id1)); + CHECK_FALSE(timer_controller.is_active(id2)); + CHECK_TRUE(timer_controller.is_active(id3)); + + // The time to next should be the what's left of the interval for id3. + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); + + // Tick the remaining time for id3 to expire. + timer_controller.tick(9); + timer_controller.handle_deferred(); + CHECK_TRUE(timer_controller.is_active(id1)); + CHECK_FALSE(timer_controller.is_active(id2)); + CHECK_TRUE(timer_controller.is_active(id3)); + + // The time to next should be the what's left of the interval for id1. + CHECK_EQUAL(1, timerTimeToNextTest.time_to_next); + + // Stop timer id3 so that id1 is the last timeout. + timer_controller.stop(id3); + + // Tick the remaining time for id1 to expire. + timer_controller.tick(1); timer_controller.handle_deferred(); CHECK_FALSE(timer_controller.is_active(id1)); CHECK_FALSE(timer_controller.is_active(id2)); CHECK_FALSE(timer_controller.is_active(id3)); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(3, timerInsertRemoveTest.removed); - } - - //************************************************************************* - TEST(message_timer_time_to_next_with_has_active_timer) - { - locks.clear(); - try_lock_type try_lock = try_lock_type::create(); - lock_type lock = lock_type::create(); - unlock_type unlock = unlock_type::create(); - - etl::callback_timer_deferred_locked<3, 3> timer_controller(try_lock, lock, unlock); - - etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Single_Shot); - etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot); - etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 11, etl::timer::mode::Single_Shot); - - timer_controller.set_insert_callback( - event_callback_type::create()); - timer_controller.set_remove_callback( - event_callback_type::create()); - - timer_controller.start(id1); - timer_controller.start(id3); - timer_controller.start(id2); - - timer_controller.enable(true); - - timer_controller.tick(11); - timer_controller.handle_deferred(); - CHECK_EQUAL(23 - 11, timer_controller.time_to_next()); - CHECK_TRUE(timer_controller.has_active_timer()); - - timer_controller.tick(23); - timer_controller.handle_deferred(); - CHECK_EQUAL(3, timer_controller.time_to_next()); - CHECK_TRUE(timer_controller.has_active_timer()); - - timer_controller.tick(2); - timer_controller.handle_deferred(); - CHECK_EQUAL(1, timer_controller.time_to_next()); - CHECK_TRUE(timer_controller.has_active_timer()); - - timer_controller.tick(1); - timer_controller.handle_deferred(); - CHECK_EQUAL(static_cast(etl::timer::interval::No_Active_Interval), timer_controller.time_to_next()); - CHECK_FALSE(timer_controller.has_active_timer()); + // There are no active timers so the time to next should be No_Active_Interval. + CHECK_EQUAL(etl::timer::interval::No_Active_Interval, timerTimeToNextTest.time_to_next); } //************************************************************************* diff --git a/test/test_callback_timer_locked.cpp b/test/test_callback_timer_locked.cpp index b87c4b8c..9ec3c6a1 100644 --- a/test/test_callback_timer_locked.cpp +++ b/test/test_callback_timer_locked.cpp @@ -127,38 +127,29 @@ namespace callback_type member_callback = callback_type::create(); callback_type member_callback2 = callback_type::create(); - class TimerInsertRemoveTest + class TimerTimeToNextTest { public: - uint32_t inserted; - uint32_t removed; - TimerInsertRemoveTest() - : inserted(0) - , removed(0) + uint32_t time_to_next; + + TimerTimeToNextTest() + : time_to_next(0) { } - void insert_handler(etl::timer::id::type id_) + void time_to_next_handler(uint32_t time_to_next_) { - (void)id_; - inserted++; - } - - void remove_handler(etl::timer::id::type id_) - { - (void)id_; - removed++; + time_to_next = time_to_next_; } void clear(void) { - inserted = 0; - removed = 0; + time_to_next = 0; } }; - TimerInsertRemoveTest timerInsertRemoveTest; + TimerTimeToNextTest timerTimeToNextTest; //*************************************************************************** // Free function callback via etl::function @@ -907,9 +898,49 @@ namespace } //************************************************************************* - TEST(callback_timer_is_active) + // Tick ID1 ID2 ID3 + // 0 . . . + // 1 . . . + // 2 . . . + // 3 . . . + // 4 . . . + // 5 . . . + // 6 . . . + // 7 . . . + // 8 . . . + // 9 . . O + // 10 . . . + // 11 . . . + // 12 . . . + // 13 . . . + // 14 . . . + // 15 . . . + // 16 . . . + // 17 . . . + // 18 . . O + // 19 . . . + // 20 . . . + // 21 . . . + // 22 . . . + // 23 . O . + // 24 . . . + // 25 . . . + // 26 . . . + // 27 . . O + // 28 . . . + // 29 . . . + // 30 . . . + // 31 . . . + // 32 . . . + // 33 . . . + // 34 . . . + // 35 . . . + // 36 . . O + // 37 O . . + // + TEST(callback_timer_is_active_and_time_to_next) { - timerInsertRemoveTest.clear(); + timerTimeToNextTest.clear(); locks.clear(); try_lock_type try_lock = try_lock_type::create(); lock_type lock = lock_type::create(); @@ -919,19 +950,16 @@ namespace etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Single_Shot); etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot); - etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 11, etl::timer::mode::Single_Shot); + etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 9, etl::timer::mode::Repeating); - timer_controller.set_insert_callback( - event_callback_type::create()); - timer_controller.set_remove_callback( - event_callback_type::create()); + timer_controller.set_time_to_next_callback( + event_callback_type::create()); timer_controller.start(id1); timer_controller.start(id3); timer_controller.start(id2); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(0, timerInsertRemoveTest.removed); + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); // The time to next should be the interval for id3. timer_controller.enable(true); @@ -939,69 +967,71 @@ namespace CHECK_TRUE(timer_controller.is_active(id2)); CHECK_TRUE(timer_controller.is_active(id3)); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(0, timerInsertRemoveTest.removed); + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); // The time to next should be the interval for id3. - timer_controller.tick(11); + // Tick the time for id3 to expire. + timer_controller.tick(9); CHECK_TRUE(timer_controller.is_active(id1)); CHECK_TRUE(timer_controller.is_active(id2)); - CHECK_FALSE(timer_controller.is_active(id3)); + CHECK_TRUE(timer_controller.is_active(id3)); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(1, timerInsertRemoveTest.removed); + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); // The time to next should be the what's left of the interval for id3. - timer_controller.tick(23 - 11); + // Stop the timer and check that the time to next is updated to that of id2. + timer_controller.stop(id3); + CHECK_EQUAL(14, timerTimeToNextTest.time_to_next); // The time to next should be the what's left of the interval for id2. + + // Start the timer again and check that the time to next is updated to the interval for id3. + timer_controller.start(id3); + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); + + // Tick the time for id3 to expire. + timer_controller.tick(9); + CHECK_TRUE(timer_controller.is_active(id1)); + CHECK_TRUE(timer_controller.is_active(id2)); + CHECK_TRUE(timer_controller.is_active(id3)); + + // The time to next should be the what's left of the interval for id2. + CHECK_EQUAL(5, timerTimeToNextTest.time_to_next); + + // Tick the remaining time for id2 to expire. + timer_controller.tick(5); CHECK_TRUE(timer_controller.is_active(id1)); CHECK_FALSE(timer_controller.is_active(id2)); - CHECK_FALSE(timer_controller.is_active(id3)); + CHECK_TRUE(timer_controller.is_active(id3)); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(2, timerInsertRemoveTest.removed); + // The time to next should be the what's left of the interval for id3. + CHECK_EQUAL(4, timerTimeToNextTest.time_to_next); - timer_controller.tick(37 - 23); + // Tick the remaining time for id3 to expire. + timer_controller.tick(4); + CHECK_TRUE(timer_controller.is_active(id1)); + CHECK_FALSE(timer_controller.is_active(id2)); + CHECK_TRUE(timer_controller.is_active(id3)); + + // The time to next should be the what's left of the interval for id3. + CHECK_EQUAL(9, timerTimeToNextTest.time_to_next); + + // Tick the remaining time for id3 to expire. + timer_controller.tick(9); + CHECK_TRUE(timer_controller.is_active(id1)); + CHECK_FALSE(timer_controller.is_active(id2)); + CHECK_TRUE(timer_controller.is_active(id3)); + + // The time to next should be the what's left of the interval for id1. + CHECK_EQUAL(1, timerTimeToNextTest.time_to_next); + + // Stop timer id3 so that id1 is the last timeout. + timer_controller.stop(id3); + + // Tick the remaining time for id1 to expire. + timer_controller.tick(1); CHECK_FALSE(timer_controller.is_active(id1)); CHECK_FALSE(timer_controller.is_active(id2)); CHECK_FALSE(timer_controller.is_active(id3)); - CHECK_EQUAL(3, timerInsertRemoveTest.inserted); - CHECK_EQUAL(3, timerInsertRemoveTest.removed); - } - - //************************************************************************* - TEST(message_timer_time_to_next_with_has_active_timer) - { - locks.clear(); - try_lock_type try_lock = try_lock_type::create(); - lock_type lock = lock_type::create(); - unlock_type unlock = unlock_type::create(); - - etl::callback_timer_locked<3> timer_controller(try_lock, lock, unlock); - - etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Single_Shot); - etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot); - etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 11, etl::timer::mode::Single_Shot); - - timer_controller.start(id1); - timer_controller.start(id3); - timer_controller.start(id2); - - timer_controller.enable(true); - - timer_controller.tick(11); - CHECK_EQUAL(12, timer_controller.time_to_next()); - CHECK_TRUE(timer_controller.has_active_timer()); - - timer_controller.tick(23); - CHECK_EQUAL(3, timer_controller.time_to_next()); - CHECK_TRUE(timer_controller.has_active_timer()); - - timer_controller.tick(2); - CHECK_EQUAL(1, timer_controller.time_to_next()); - CHECK_TRUE(timer_controller.has_active_timer()); - - timer_controller.tick(1); - CHECK_EQUAL(static_cast(etl::timer::interval::No_Active_Interval), timer_controller.time_to_next()); - CHECK_FALSE(timer_controller.has_active_timer()); + // There are no active timers so the time to next should be No_Active_Interval. + CHECK_EQUAL(etl::timer::interval::No_Active_Interval, timerTimeToNextTest.time_to_next); } //*************************************************************************