From f1d188e60c37f00a5a0a85c5b01319d4ac8e9b2b Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 25 Oct 2026 10:55:24 +0000 Subject: [PATCH] Updated tests Modified node end() and 'time to next' notification callback --- include/etl/intrusive_timer.h | 99 +++-- include/etl/timer_node.h | 25 +- test/test_intrusive_timer.cpp | 758 ++++++++++++++++------------------ 3 files changed, 447 insertions(+), 435 deletions(-) diff --git a/include/etl/intrusive_timer.h b/include/etl/intrusive_timer.h index e4566c88..4b0284e5 100644 --- a/include/etl/intrusive_timer.h +++ b/include/etl/intrusive_timer.h @@ -33,6 +33,10 @@ SOFTWARE. #include "nullptr.h" #include "timer_node.h" +#if ETL_HAS_ATOMIC + #include "atomic.h" +#endif + #include "private/timer_lists.h" #include @@ -62,7 +66,7 @@ namespace etl /// The callback type for notifying the user of the next timer that is due to expire. /// Either returns a pointer to the next timer that is due to expire or etl::timer_node::end() if there is no next timer. //******************************************* - typedef etl::delegate timer_notification_callback_type; + typedef etl::delegate time_to_next_notification_type; //******************************************* /// Constructor. @@ -87,7 +91,7 @@ namespace etl lock_policy.lock(); - if (!timer_.is_registered(this)) + if (!timer_.is_registered()) { timer_.set_id(get_next_id()); register_list.insert(timer_); @@ -110,12 +114,14 @@ namespace etl lock_policy.lock(); bool result = false; + bool notify = false; - if (timer_.is_registered(this)) + if (timer_.is_registered_with(this)) { if (timer_.is_active()) { - active_list.remove(&timer_); + notify = (active_list.first() == &timer_); + stop_timer(timer_); } register_list.remove(&timer_); @@ -125,8 +131,17 @@ namespace etl result = true; } + // Get the next timer that is due to expire. + etl::timer_node* next_timer = active_list.first(); + lock_policy.unlock(); + if (notify) + { + // The next timer has changed, so notify the user. + time_to_next_notification.call_if(next_timer->get_delta()); + } + return result; } @@ -209,7 +224,7 @@ namespace etl has_active = !active_list.empty(); - notify = true; + notify = has_active; } if (has_active) @@ -230,7 +245,7 @@ namespace etl if (notify) { // The next timer has changed, so notify the user. - next_timer_notification.call_if(next_timer); + time_to_next_notification.call_if(next_timer->get_delta()); } // Invoke all of the expired timers. @@ -249,15 +264,17 @@ namespace etl lock_policy.lock(); - if (timer_.is_registered(this)) + if (timer_.is_registered_with(this)) { - if (!timer_.is_active()) + // Must not be active and must have a valid period. + if (!timer_.is_active() && (timer_.get_period() != etl::timer::interval::No_Active_Interval)) { active_list.insert(timer_); is_started = true; } } + // Is this the next timer that is due to expire? bool notify = (active_list.first() == &timer_); lock_policy.unlock(); @@ -265,13 +282,13 @@ namespace etl if (is_started && immediate_) { // Trigger the timer immediately. - timer_.invoke(timer_.get_config()); + timer_.invoke(); } if (notify) { // The next timer has changed, so notify the user. - next_timer_notification.call_if(active_list.first()); + time_to_next_notification.call_if(timer_.get_delta()); } return is_started; @@ -283,28 +300,26 @@ namespace etl bool stop(etl::timer_node& timer_) ETL_NOEXCEPT { bool is_stopped = false; + bool notify = false; lock_policy.lock(); - bool notify = false; - if (timer_.is_active()) { notify = (active_list.first() == &timer_); - stop_impl(timer_); + stop_timer(timer_); is_stopped = true; } // Get the next timer that is due to expire. etl::timer_node* next_timer = active_list.first(); + notify = true; + lock_policy.unlock(); - if (notify) - { - // The next timer has changed, so notify the user. - next_timer_notification.call_if(next_timer); - } + // The next timer has changed, so notify the user. + time_to_next_notification.call_if(next_timer->get_delta()); return is_stopped; } @@ -320,12 +335,12 @@ namespace etl bool notify = false; - if (timer_.is_registered(this)) + if (timer_.is_registered_with(this)) { if (timer_.is_active()) { notify = (active_list.first() == &timer_); - stop_impl(timer_); + stop_timer(timer_); } timer_.set_period(period_); @@ -340,7 +355,7 @@ namespace etl if (notify) { // The next timer has changed, so notify the user. - next_timer_notification.call_if(next_timer); + time_to_next_notification.call_if(next_timer->get_delta()); } return result; @@ -357,12 +372,12 @@ namespace etl bool notify = false; - if (timer_.is_registered(this)) + if (timer_.is_registered_with(this)) { if (timer_.is_active()) { notify = (active_list.first() == &timer_); - stop_impl(timer_); + stop_timer(timer_); } timer_.set_mode(mode_); result = true; @@ -376,7 +391,7 @@ namespace etl if (notify) { // The next timer has changed, so notify the user. - next_timer_notification.call_if(next_timer); + time_to_next_notification.call_if(next_timer->get_delta()); } return result; @@ -426,17 +441,36 @@ namespace etl //******************************************* /// Sets the update notification. //******************************************* - void set_update_notification(timer_notification_callback_type callback) ETL_NOEXCEPT + void set_next_timer_notification(time_to_next_notification_type callback) ETL_NOEXCEPT { - next_timer_notification = callback; + time_to_next_notification = callback; } //******************************************* /// Clears the update notification. //******************************************* - void clear_time_next_notification() ETL_NOEXCEPT + void clear_next_timer_notification() ETL_NOEXCEPT { - next_timer_notification.clear(); + time_to_next_notification.clear(); + } + + //******************************************* + /// Finds a timer by its id. + //******************************************* + etl::timer_node* find_timer(etl::timer::id::type id_) ETL_NOEXCEPT + { + etl::timer_node* timer = register_list.first(); + + while (timer != register_list.end()) + { + if (timer->get_id() == id_) + { + return timer; + } + + timer = register_list.next(timer); + } + return etl::timer_node::end(); } private: @@ -473,7 +507,7 @@ namespace etl //******************************************* /// Stops a timer without locking. //******************************************* - void stop_impl(etl::timer_node& timer_) ETL_NOEXCEPT + void stop_timer(etl::timer_node& timer_) ETL_NOEXCEPT { active_list.remove(&timer_); } @@ -488,10 +522,7 @@ namespace etl while (timer != expired_list.end()) { - const etl::timer_config& config = timer->get_config(); - - timer->invoke(config); - + timer->invoke(); timer = expired_list.next(timer); } @@ -506,7 +537,7 @@ namespace etl etl::private_timer::timer_active_list active_list; etl::private_timer::timer_expired_list expired_list; - timer_notification_callback_type next_timer_notification; + time_to_next_notification_type time_to_next_notification; bool enabled; size_t timer_count; diff --git a/include/etl/timer_node.h b/include/etl/timer_node.h index cfdda44d..30948913 100644 --- a/include/etl/timer_node.h +++ b/include/etl/timer_node.h @@ -234,7 +234,7 @@ namespace etl //*************************************************************************** static etl::timer_node* end() ETL_NOEXCEPT { - static etl::timer_node sentinel_node(etl::timer_config(0, 0)); + static etl::timer_node sentinel_node(etl::timer_config(etl::timer::interval::No_Active_Interval, etl::timer::mode::Single_Shot)); return &sentinel_node; } @@ -297,11 +297,20 @@ namespace etl /// Returns true if the timer is registered to this owner. /// A timer cannot be registered to more than one owner. //******************************************* - bool is_registered(void* owner_) const ETL_NOEXCEPT + bool is_registered_with(void* owner_) const ETL_NOEXCEPT { return (registered_next != unlinked()) && (owner == owner_); } + //******************************************* + /// Returns true if the timer is registered to this owner. + /// A timer cannot be registered to more than one owner. + //******************************************* + bool is_registered() const ETL_NOEXCEPT + { + return (registered_next != unlinked()) && (owner != ETL_NULLPTR); + } + //******************************************* /// Returns true if the timer is active. //******************************************* @@ -321,7 +330,7 @@ namespace etl //******************************************* /// Invokes the timer's callback. //******************************************* - virtual void invoke(const etl::timer_config& /*config*/) + virtual void invoke() { // Default implementation does nothing. } @@ -345,7 +354,7 @@ namespace etl //******************************************* /// Constructor. //******************************************* - timer_callback_node(TCallback callback_, const etl::timer_config& config_) ETL_NOEXCEPT + timer_callback_node(const etl::timer_config& config_, TCallback callback_) ETL_NOEXCEPT : timer_node(config_) , callback(callback_) { @@ -354,9 +363,9 @@ namespace etl //******************************************* /// Invokes the timer's callback. //******************************************* - virtual void invoke(const etl::timer_config& config) ETL_OVERRIDE + virtual void invoke() ETL_OVERRIDE { - callback(config); + callback(); } TCallback callback; ///< The callback delegate for the timer. @@ -381,10 +390,8 @@ namespace etl //******************************************* /// Invokes the timer's callback. //******************************************* - virtual void invoke(const etl::timer_config& config) ETL_OVERRIDE + virtual void invoke() ETL_OVERRIDE { - message.set_timer_config(config); - router->receive(message); } diff --git a/test/test_intrusive_timer.cpp b/test/test_intrusive_timer.cpp index f8eb5b0a..51396f40 100644 --- a/test/test_intrusive_timer.cpp +++ b/test/test_intrusive_timer.cpp @@ -136,19 +136,23 @@ namespace }; //************************************************************************* - using CallbackDelegate = etl::delegate; + using CallbackDelegate = etl::delegate; using CallbackTimer = etl::timer_callback_node; //************************************************************************* - bool global_callback_called = false; - const etl::timer_config* global_config; - uint64_t global_tick_count = 0; + bool global_callback_called = false; + uint64_t global_call_count = 0; - static void global_callback(const etl::timer_config& config) + static void global_callback() { global_callback_called = true; - global_config = &config; - global_tick_count = ticks; + ++global_call_count; + } + + void global_callback_clear() + { + global_callback_called = false; + global_call_count = 0; } //************************************************************************* @@ -158,21 +162,24 @@ namespace Object() : member_callback_called(false) - , member_config(ETL_NULLPTR) - , member_tick_count(0) + , member_call_count(0) { } - void member(const etl::timer_config& config) + void member() { member_callback_called = true; - member_config = &config; - member_tick_count = ticks; + ++member_call_count; } - bool member_callback_called = false; - const etl::timer_config* member_config; - uint64_t member_tick_count; + void clear() + { + member_callback_called = false; + member_call_count = 0; + } + + bool member_callback_called; + uint64_t member_call_count; }; static Object object; @@ -186,11 +193,6 @@ namespace { } - void set_timer_config(const etl::timer_config& config_) - { - config = &config_; - } - int value; const etl::timer_config* config; }; @@ -202,8 +204,8 @@ namespace MessageProcessor() : etl::message_router() , message_callback_called(false) - , message_config(ETL_NULLPTR) , message_value(0) + , message_call_count(0) { } @@ -211,18 +213,24 @@ namespace void on_receive(const CallbackMessage& msg) { message_callback_called = true; - message_config = msg.config; message_value = msg.value; - message_tick_count = ticks; + ++message_call_count; } //******************************************* void on_receive_unknown(const etl::imessage& msg) {} - bool message_callback_called; - const etl::timer_config* message_config; - int message_value; - uint64_t message_tick_count; + //******************************************* + void clear() + { + message_callback_called = false; + message_value = 0; + message_call_count = 0; + } + + bool message_callback_called; + int message_value; + uint64_t message_call_count; }; using MessageTimer = etl::timer_message_node; @@ -231,29 +239,19 @@ namespace CallbackMessage callback_message(42); //************************************************************************* - // Notification of the next timer that is due to expire. + // Notification of the time to the next timer that is due to expire. //************************************************************************* - struct notification_result_type + std::vector time_to_next; + + //*********************************** + /// Notification of the time to the next timer, from the intrusive timer. + //*********************************** + void next_timer_notification(uint32_t delta) { - void clear() - { - timer = etl::timer_node::end(); - notified = false; - } - - const etl::timer_node* timer; - bool notified; - }; - - notification_result_type notification_result; - - void next_timer_notification(const etl::timer_node* timer_) - { - notification_result.notified = true; - notification_result.timer = timer_; + time_to_next.push_back(delta); } - using notification_type = etl::intrusive_timer::timer_notification_callback_type; + using notification_type = etl::intrusive_timer::time_to_next_notification_type; notification_type notification_delegate = notification_type::create(next_timer_notification); @@ -293,7 +291,61 @@ namespace } //************************************************************************* - TEST(test_intrusive_timer_unregister_timers_by_node) + TEST(test_intrusive_timer_double_register_timers) + { + LockPolicy lock_policy; + + etl::intrusive_timer timer_controller1(lock_policy); + etl::intrusive_timer timer_controller2(lock_policy); + + etl::timer_node node1(etl::timer_config(100, etl::timer::mode::Single_Shot)); + + bool success = false; + + // Register the timer with the first controller twice. + success = timer_controller1.register_timer(node1); + CHECK_TRUE(success); + success = timer_controller1.register_timer(node1); + CHECK_FALSE(success); + CHECK_EQUAL(1U, timer_controller1.number_of_timers()); + + // Register the same timer with the second controller. + success = timer_controller2.register_timer(node1); + CHECK_FALSE(success); + CHECK_EQUAL(0U, timer_controller2.number_of_timers()); + } + + //************************************************************************* + TEST(test_intrusive_timer_find_timers) + { + LockPolicy lock_policy; + + etl::intrusive_timer timer_controller(lock_policy); + + etl::timer_node node1(etl::timer_config(100, etl::timer::mode::Repeating)); + etl::timer_node node2(etl::timer_config(200, etl::timer::mode::Repeating)); + etl::timer_node node3(etl::timer_config(300, etl::timer::mode::Repeating)); + etl::timer_node node4(etl::timer_config(400, etl::timer::mode::Repeating)); + + timer_controller.register_timer(node1); + timer_controller.register_timer(node2); + timer_controller.register_timer(node3); + + // Check the ids are valid, except for the unregistered node4. + CHECK_FALSE(node1.get_id() == etl::timer::id::No_Timer); + CHECK_FALSE(node2.get_id() == etl::timer::id::No_Timer); + CHECK_FALSE(node3.get_id() == etl::timer::id::No_Timer); + CHECK_TRUE(node4.get_id() == etl::timer::id::No_Timer); + + // Check we can find the timers by their id. + CHECK_EQUAL(&node1, timer_controller.find_timer(node1.get_id())); + CHECK_EQUAL(&node2, timer_controller.find_timer(node2.get_id())); + CHECK_EQUAL(&node3, timer_controller.find_timer(node3.get_id())); + CHECK_EQUAL(etl::timer_node::end(), timer_controller.find_timer(node4.get_id())); + } + + //************************************************************************* + TEST(test_intrusive_timer_unregister_timers) { LockPolicy lock_policy; @@ -360,30 +412,36 @@ namespace LockPolicy lock_policy; etl::intrusive_timer timer_controller(lock_policy); + timer_controller.set_next_timer_notification(notification_delegate); + time_to_next.clear(); + global_callback_clear(); etl::timer_config config1(37, etl::timer::mode::Single_Shot); CallbackDelegate callback_delegate1 = CallbackDelegate::create(global_callback); - CallbackTimer callback_timer1(callback_delegate1, config1); + CallbackTimer callback_timer1(config1, callback_delegate1); + object.clear(); etl::timer_config config2(23, etl::timer::mode::Single_Shot); CallbackDelegate callback_delegate2 = CallbackDelegate::create(); - CallbackTimer callback_timer2(callback_delegate2, config2); + CallbackTimer callback_timer2(config2, callback_delegate2); + message_processor.clear(); etl::timer_config config3(11, etl::timer::mode::Single_Shot); MessageTimer callback_timer3(config3, message_processor, callback_message); - CHECK_TRUE(timer_controller.register_timer(callback_timer1)); - CHECK_TRUE(timer_controller.register_timer(callback_timer2)); - CHECK_TRUE(timer_controller.register_timer(callback_timer3)); + timer_controller.register_timer(callback_timer1); + timer_controller.register_timer(callback_timer2); + timer_controller.register_timer(callback_timer3); - // Get the modified id of the timers after registration. - etl::timer::id::type config1_id = callback_timer1.get_id(); - etl::timer::id::type config2_id = callback_timer2.get_id(); - etl::timer::id::type config3_id = callback_timer3.get_id(); + timer_controller.start(callback_timer1); // 37, the first timer started is the first due to expire. + timer_controller.start(callback_timer3); // 11, the second timer started is now first due to expire, 37 is second. + timer_controller.start(callback_timer2); // 23, the third timer started is now second due to expire.37 is third. - timer_controller.start(callback_timer1); - timer_controller.start(callback_timer3); - timer_controller.start(callback_timer2); + // Check the notifications. + CHECK_EQUAL(37, time_to_next[0]); // 37, the first timer started is the first due to expire. + CHECK_EQUAL(11, time_to_next[1]); // 11, the second timer started is now first due to expire. + + time_to_next.clear(); timer_controller.enable(true); @@ -391,344 +449,260 @@ namespace const uint32_t step = 1UL; - while (ticks <= 110U) + while (ticks <= 100U) { ticks += step; timer_controller.tick(step); } CHECK_TRUE(global_callback_called); - CHECK_EQUAL((int)config1_id, (int)global_config->get_id()); - CHECK_EQUAL(config1.get_mode(), global_config->get_mode()); - CHECK_EQUAL(config1.get_period(), global_config->get_period()); - CHECK_EQUAL(config1.get_period(), global_tick_count); - - CHECK_TRUE(object.member_callback_called); - CHECK_EQUAL((int)config2_id, (int)object.member_config->get_id()); - CHECK_EQUAL(config2.get_mode(), object.member_config->get_mode()); - CHECK_EQUAL(config2.get_period(), object.member_config->get_period()); - CHECK_EQUAL(config2.get_period(), object.member_tick_count); + CHECK_EQUAL(1, global_call_count); CHECK_TRUE(message_processor.message_callback_called); - CHECK_EQUAL((int)config3_id, (int)message_processor.message_config->get_id()); - CHECK_EQUAL(config3.get_mode(), message_processor.message_config->get_mode()); - CHECK_EQUAL(config3.get_period(), message_processor.message_config->get_period()); - CHECK_EQUAL(callback_message.value, message_processor.message_value); - CHECK_EQUAL(config3.get_period(), message_processor.message_tick_count); + CHECK_EQUAL(1, message_processor.message_call_count); + + // Check the notifications. + CHECK_EQUAL(12, time_to_next[0]); // 23, the next after 11 expired. + CHECK_EQUAL(14, time_to_next[1]); // 37, the next after 23 expired. + + time_to_next.clear(); + } + + //************************************************************************* + TEST(test_intrusive_timer_repeating) + { + LockPolicy lock_policy; + + etl::intrusive_timer timer_controller(lock_policy); + timer_controller.set_next_timer_notification(notification_delegate); + time_to_next.clear(); + + global_callback_clear(); + etl::timer_config config1(37, etl::timer::mode::Repeating); + CallbackDelegate callback_delegate1 = CallbackDelegate::create(global_callback); + CallbackTimer callback_timer1(config1, callback_delegate1); + + object.clear(); + etl::timer_config config2(23, etl::timer::mode::Repeating); + CallbackDelegate callback_delegate2 = CallbackDelegate::create(); + CallbackTimer callback_timer2(config2, callback_delegate2); + + message_processor.clear(); + etl::timer_config config3(11, etl::timer::mode::Repeating); + MessageTimer callback_timer3(config3, message_processor, callback_message); + + timer_controller.register_timer(callback_timer1); + timer_controller.register_timer(callback_timer2); + timer_controller.register_timer(callback_timer3); + + timer_controller.start(callback_timer1); // 37, the first timer started is the first due to expire. + timer_controller.start(callback_timer3); // 11, the second timer started is now first due to expire, 37 is second. + timer_controller.start(callback_timer2); // 23, the third timer started is now second due to expire.37 is third. + + // Check the notifications. + CHECK_EQUAL(37, time_to_next[0]); // 37, the first timer started is the first due to expire. + CHECK_EQUAL(11, time_to_next[1]); // 11, the second timer started is now first due to expire. + + time_to_next.clear(); + + timer_controller.enable(true); + + ticks = 0; + + const uint32_t step = 1UL; + + while (ticks <= 100U) + { + ticks += step; + timer_controller.tick(step); + } + + // Check the callback counts. + CHECK_TRUE(global_callback_called); + CHECK_EQUAL(2, global_call_count); + + CHECK_TRUE(object.member_callback_called); + CHECK_EQUAL(4, object.member_call_count); + + CHECK_TRUE(message_processor.message_callback_called); + CHECK_EQUAL(9, message_processor.message_call_count); + + // Check the notifications. + CHECK_EQUAL(11, time_to_next[0]); + CHECK_EQUAL(1, time_to_next[1]); + CHECK_EQUAL(10, time_to_next[2]); + CHECK_EQUAL(4, time_to_next[3]); + CHECK_EQUAL(7, time_to_next[4]); + CHECK_EQUAL(2, time_to_next[5]); + CHECK_EQUAL(9, time_to_next[6]); + CHECK_EQUAL(11, time_to_next[7]); + CHECK_EQUAL(3, time_to_next[8]); + CHECK_EQUAL(5, time_to_next[9]); + CHECK_EQUAL(3, time_to_next[10]); + CHECK_EQUAL(11, time_to_next[11]); + CHECK_EQUAL(4, time_to_next[12]); + CHECK_EQUAL(7, time_to_next[13]); + CHECK_EQUAL(11, time_to_next[14]); + + time_to_next.clear(); + } + + //************************************************************************* + TEST(test_intrusive_timer_repeating_bigger_step) + { + LockPolicy lock_policy; + + etl::intrusive_timer timer_controller(lock_policy); + timer_controller.set_next_timer_notification(notification_delegate); + time_to_next.clear(); + + global_callback_clear(); + etl::timer_config config1(37, etl::timer::mode::Repeating); + CallbackDelegate callback_delegate1 = CallbackDelegate::create(global_callback); + CallbackTimer callback_timer1(config1, callback_delegate1); + + object.clear(); + etl::timer_config config2(23, etl::timer::mode::Repeating); + CallbackDelegate callback_delegate2 = CallbackDelegate::create(); + CallbackTimer callback_timer2(config2, callback_delegate2); + + message_processor.clear(); + etl::timer_config config3(11, etl::timer::mode::Repeating); + MessageTimer callback_timer3(config3, message_processor, callback_message); + + timer_controller.register_timer(callback_timer1); + timer_controller.register_timer(callback_timer2); + timer_controller.register_timer(callback_timer3); + + timer_controller.start(callback_timer1); // 37, the first timer started is the first due to expire. + timer_controller.start(callback_timer3); // 11, the second timer started is now first due to expire, 37 is second. + timer_controller.start(callback_timer2); // 23, the third timer started is now second due to expire.37 is third. + + // Check the notifications. + CHECK_EQUAL(37, time_to_next[0]); // 37, the first timer started is the first due to expire. + CHECK_EQUAL(11, time_to_next[1]); // 11, the second timer started is now first due to expire. + + time_to_next.clear(); + + timer_controller.enable(true); + + ticks = 0; + + const uint32_t step = 3UL; + + while (ticks <= 100U) + { + ticks += step; + timer_controller.tick(step); + } + + // Check the callback counts. + CHECK_TRUE(global_callback_called); + CHECK_EQUAL(2, global_call_count); + + CHECK_TRUE(object.member_callback_called); + CHECK_EQUAL(4, object.member_call_count); + + CHECK_TRUE(message_processor.message_callback_called); + CHECK_EQUAL(9, message_processor.message_call_count); + + // Check the notifications. + CHECK_EQUAL(10, time_to_next[0]); + CHECK_EQUAL(9, time_to_next[1]); + CHECK_EQUAL(4, time_to_next[2]); + CHECK_EQUAL(5, time_to_next[3]); + CHECK_EQUAL(1, time_to_next[4]); + CHECK_EQUAL(7, time_to_next[5]); + CHECK_EQUAL(9, time_to_next[6]); + CHECK_EQUAL(3, time_to_next[7]); + CHECK_EQUAL(5, time_to_next[8]); + CHECK_EQUAL(2, time_to_next[9]); + CHECK_EQUAL(10, time_to_next[10]); + CHECK_EQUAL(2, time_to_next[11]); + CHECK_EQUAL(6, time_to_next[12]); + CHECK_EQUAL(11, time_to_next[13]); + + time_to_next.clear(); + } + + //************************************************************************* + TEST(test_intrusive_timer_repeating_register_unregister) + { + LockPolicy lock_policy; + + etl::intrusive_timer timer_controller(lock_policy); + timer_controller.set_next_timer_notification(notification_delegate); + time_to_next.clear(); + + global_callback_clear(); + etl::timer_config config1(37, etl::timer::mode::Repeating); + CallbackDelegate callback_delegate1 = CallbackDelegate::create(global_callback); + CallbackTimer callback_timer1(config1, callback_delegate1); + + object.clear(); + etl::timer_config config2(23, etl::timer::mode::Repeating); + CallbackDelegate callback_delegate2 = CallbackDelegate::create(); + CallbackTimer callback_timer2(config2, callback_delegate2); + + message_processor.clear(); + etl::timer_config config3(11, etl::timer::mode::Repeating); + MessageTimer callback_timer3(config3, message_processor, callback_message); + + timer_controller.register_timer(callback_timer2); + timer_controller.register_timer(callback_timer3); + + timer_controller.start(callback_timer3); + timer_controller.start(callback_timer2); + + timer_controller.enable(true); + + ticks = 0; + + const uint32_t step = 1U; + + while (ticks <= 100U) + { + if (ticks == 36) + { + timer_controller.unregister_timer(callback_timer2); + + timer_controller.register_timer(callback_timer1); + timer_controller.start(callback_timer1); + } + + ticks += step; + timer_controller.tick(step); + } + + // Check the callback counts. + CHECK_TRUE(global_callback_called); + CHECK_EQUAL(1, global_call_count); + + CHECK_TRUE(object.member_callback_called); + CHECK_EQUAL(1, object.member_call_count); + + CHECK_TRUE(message_processor.message_callback_called); + CHECK_EQUAL(9, message_processor.message_call_count); + + // Check the notifications. + CHECK_EQUAL(11, time_to_next[0]); // Start to timer3 + CHECK_EQUAL(11, time_to_next[1]); // to timer3 + CHECK_EQUAL(1, time_to_next[2]); // to timer2 + CHECK_EQUAL(10, time_to_next[3]); // to timer3 + CHECK_EQUAL(11, time_to_next[4]); // to timer3 + CHECK_EQUAL(11, time_to_next[5]); // to timer3 + CHECK_EQUAL(11, time_to_next[6]); // to timer3 + CHECK_EQUAL(7, time_to_next[7]); // to timer1 + CHECK_EQUAL(4, time_to_next[8]); // to timer3 + CHECK_EQUAL(11, time_to_next[9]); // to timer3 + CHECK_EQUAL(11, time_to_next[10]); // to timer3 + CHECK_EQUAL(11, time_to_next[11]); // to timer3 + + time_to_next.clear(); } // //************************************************************************* - // TEST(message_timer_one_shot_after_timeout) - // { - // etl::intrusive_timer<1> timer_controller; - // - // etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Single_Shot); - // object.tick_list.clear(); - // - // timer_controller.start(id1); - // timer_controller.enable(true); - // - // ticks = 0; - // - // const uint32_t step = 1U; - // - // while (ticks <= 100U) - // { - // ticks += step; - // timer_controller.tick(step); - // } - // - // // Timer should have timed out. - // - // CHECK(timer_controller.set_period(id1, 50)); - // timer_controller.start(id1); - // - // object.tick_list.clear(); - // - // ticks = 0; - // - // while (ticks <= 100U) - // { - // ticks += step; - // timer_controller.tick(step); - // } - // - // // Timer should have timed out. - // - // CHECK_EQUAL(50U, *object.tick_list.data()); - // - // CHECK(timer_controller.unregister_timer(id1)); - // CHECK(!timer_controller.unregister_timer(id1)); - // CHECK(!timer_controller.start(id1)); - // CHECK(!timer_controller.stop(id1)); - // } - // - // //************************************************************************* - // TEST(intrusive_timer_repeating) - // { - // etl::intrusive_timer<3> timer_controller; - // - // etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Repeating); - // etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Repeating); - // etl::timer::id::type id3 = timer_controller.register_timer(free_callback2, 11, etl::timer::mode::Repeating); - // - // object.tick_list.clear(); - // free_tick_list1.clear(); - // free_tick_list2.clear(); - // - // timer_controller.start(id1); - // timer_controller.start(id3); - // timer_controller.start(id2); - // - // timer_controller.enable(true); - // - // ticks = 0; - // - // const uint32_t step = 1U; - // - // while (ticks <= 100U) - // { - // ticks += step; - // timer_controller.tick(step); - // } - // - // std::vector compare1 = {37, 74}; - // std::vector compare2 = {23, 46, 69, 92}; - // std::vector compare3 = {11, 22, 33, 44, 55, 66, 77, 88, 99}; - // - // CHECK(object.tick_list.size() != 0); - // CHECK(free_tick_list1.size() != 0); - // CHECK(free_tick_list2.size() != 0); - // - // CHECK_ARRAY_EQUAL(compare1.data(), object.tick_list.data(), compare1.size()); - // CHECK_ARRAY_EQUAL(compare2.data(), free_tick_list1.data(), compare2.size()); - // CHECK_ARRAY_EQUAL(compare3.data(), free_tick_list2.data(), compare3.size()); - // } - // - // //************************************************************************* - // TEST(intrusive_timer_repeating_bigger_step) - // { - // etl::intrusive_timer<3> timer_controller; - // - // etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Repeating); - // etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Repeating); - // etl::timer::id::type id3 = timer_controller.register_timer(free_callback2, 11, etl::timer::mode::Repeating); - // - // object.tick_list.clear(); - // free_tick_list1.clear(); - // free_tick_list2.clear(); - // - // timer_controller.start(id1); - // timer_controller.start(id3); - // timer_controller.start(id2); - // - // CHECK(!timer_controller.is_running()); - // - // timer_controller.enable(true); - // - // CHECK(timer_controller.is_running()); - // - // ticks = 0; - // - // const uint32_t step = 5U; - // - // while (ticks <= 100U) - // { - // ticks += step; - // timer_controller.tick(step); - // } - // - // std::vector compare1 = {40, 75}; - // std::vector compare2 = {25, 50, 70, 95}; - // std::vector compare3 = {15, 25, 35, 45, 55, 70, 80, 90, 100}; - // - // CHECK(object.tick_list.size() != 0); - // CHECK(free_tick_list1.size() != 0); - // CHECK(free_tick_list2.size() != 0); - // - // CHECK_ARRAY_EQUAL(compare1.data(), object.tick_list.data(), compare1.size()); - // CHECK_ARRAY_EQUAL(compare2.data(), free_tick_list1.data(), compare2.size()); - // CHECK_ARRAY_EQUAL(compare3.data(), free_tick_list2.data(), compare3.size()); - // } - // - // //************************************************************************* - // TEST(intrusive_timer_repeating_stop_start) - // { - // etl::intrusive_timer<3> timer_controller; - // - // etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Repeating); - // etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Repeating); - // etl::timer::id::type id3 = timer_controller.register_timer(free_callback2, 11, etl::timer::mode::Repeating); - // - // object.tick_list.clear(); - // free_tick_list1.clear(); - // free_tick_list2.clear(); - // - // timer_controller.start(id3); - // timer_controller.start(id2); - // - // timer_controller.enable(true); - // - // ticks = 0; - // - // const uint32_t step = 1U; - // - // while (ticks <= 100U) - // { - // if (ticks == 40) - // { - // timer_controller.start(id1); - // timer_controller.stop(id2); - // } - // - // if (ticks == 80) - // { - // timer_controller.stop(id1); - // timer_controller.start(id2); - // } - // - // ticks += step; - // timer_controller.tick(step); - // } - // - // std::vector compare1 = {77}; - // std::vector compare2 = {23}; - // std::vector compare3 = {11, 22, 33, 44, 55, 66, 77, 88, 99}; - // - // CHECK(object.tick_list.size() != 0); - // CHECK(free_tick_list1.size() != 0); - // CHECK(free_tick_list2.size() != 0); - // - // CHECK_ARRAY_EQUAL(compare1.data(), object.tick_list.data(), compare1.size()); - // CHECK_ARRAY_EQUAL(compare2.data(), free_tick_list1.data(), compare2.size()); - // CHECK_ARRAY_EQUAL(compare3.data(), free_tick_list2.data(), compare3.size()); - // } - // - // //************************************************************************* - // TEST(intrusive_timer_timer_starts_timer_small_step) - // { - // etl::intrusive_timer<3> timer_controller; - // - // etl::timer::id::type id1 = timer_controller.register_timer(member_callback2, 100, etl::timer::mode::Single_Shot); - // etl::timer::id::type id2 = timer_controller.register_timer(member_callback, 10, etl::timer::mode::Single_Shot); - // etl::timer::id::type id3 = timer_controller.register_timer(member_callback, 22, etl::timer::mode::Single_Shot); - // - // (void)id2; - // (void)id3; - // - // object.set_controller(timer_controller); - // - // object.tick_list.clear(); - // - // timer_controller.start(id1); - // - // timer_controller.enable(true); - // - // ticks = 0; - // - // const uint32_t step = 1U; - // - // while (ticks <= 200U) - // { - // ticks += step; - // timer_controller.tick(step); - // } - // - // std::vector compare1 = {100, 110, 122}; - // - // CHECK(object.tick_list.size() != 0); - // - // CHECK_ARRAY_EQUAL(compare1.data(), object.tick_list.data(), compare1.size()); - // } - // - // //************************************************************************* - // TEST(intrusive_timer_timer_starts_timer_big_step) - // { - // etl::intrusive_timer<3> timer_controller; - // - // etl::timer::id::type id1 = timer_controller.register_timer(member_callback2, 100, etl::timer::mode::Single_Shot); - // etl::timer::id::type id2 = timer_controller.register_timer(member_callback, 10, etl::timer::mode::Single_Shot); - // etl::timer::id::type id3 = timer_controller.register_timer(member_callback, 22, etl::timer::mode::Single_Shot); - // - // (void)id2; - // (void)id3; - // - // object.set_controller(timer_controller); - // - // object.tick_list.clear(); - // - // timer_controller.start(id1); - // - // timer_controller.enable(true); - // - // ticks = 0; - // - // const uint32_t step = 3; - // - // while (ticks <= 200U) - // { - // ticks += step; - // timer_controller.tick(step); - // } - // - // std::vector compare1 = {102, 111, 123}; - // - // CHECK(object.tick_list.size() != 0); - // - // CHECK_ARRAY_EQUAL(compare1.data(), object.tick_list.data(), compare1.size()); - // } - // - // //************************************************************************* - // TEST(intrusive_timer_repeating_register_unregister) - // { - // etl::intrusive_timer<3> timer_controller; - // - // etl::timer::id::type id1; - // etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Repeating); - // etl::timer::id::type id3 = timer_controller.register_timer(free_callback2, 11, etl::timer::mode::Repeating); - // - // object.tick_list.clear(); - // free_tick_list1.clear(); - // free_tick_list2.clear(); - // - // timer_controller.start(id3); - // timer_controller.start(id2); - // - // timer_controller.enable(true); - // - // ticks = 0; - // - // const uint32_t step = 1U; - // - // while (ticks <= 100U) - // { - // if (ticks == 40) - // { - // timer_controller.unregister_timer(id2); - // - // id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Repeating); - // timer_controller.start(id1); - // } - // - // ticks += step; - // timer_controller.tick(step); - // } - // - // std::vector compare1 = {77}; - // std::vector compare2 = {23}; - // std::vector compare3 = {11, 22, 33, 44, 55, 66, 77, 88, 99}; - // - // CHECK(object.tick_list.size() != 0); - // CHECK(free_tick_list1.size() != 0); - // CHECK(free_tick_list2.size() != 0); - // - // CHECK_ARRAY_EQUAL(compare1.data(), object.tick_list.data(), compare1.size()); - // CHECK_ARRAY_EQUAL(compare2.data(), free_tick_list1.data(), compare2.size()); - // CHECK_ARRAY_EQUAL(compare3.data(), free_tick_list2.data(), compare3.size()); - // } - // - // //************************************************************************* - // TEST(intrusive_timer_repeating_clear) + // TEST(test_intrusive_timer_repeating_clear) // { // etl::intrusive_timer<3> timer_controller; // @@ -776,7 +750,7 @@ namespace // } // // //************************************************************************* - // TEST(intrusive_timer_delayed_immediate) + // TEST(test_intrusive_timer_delayed_immediate) // { // etl::intrusive_timer<3> timer_controller; // @@ -819,7 +793,7 @@ namespace // } // // //************************************************************************* - // TEST(intrusive_timer_one_shot_big_step_short_delay_insert) + // TEST(test_intrusive_timer_one_shot_big_step_short_delay_insert) // { // etl::intrusive_timer<3> timer_controller; // @@ -855,7 +829,7 @@ namespace // } // // //************************************************************************* - // TEST(intrusive_timer_one_shot_empty_list_huge_tick_before_insert) + // TEST(test_intrusive_timer_one_shot_empty_list_huge_tick_before_insert) // { // etl::intrusive_timer<3> timer_controller; // @@ -989,7 +963,7 @@ namespace // // using callback_type = etl::iintrusive_timer::callback_type; // - // TEST(intrusive_timer_call_etl_delegate) + // TEST(test_intrusive_timer_call_etl_delegate) // { // test_object test_obj; // callback_type delegate_callback = callback_type::create(test_obj); @@ -1008,7 +982,7 @@ namespace // } // // //************************************************************************* - // TEST(intrusive_timer_is_active) + // TEST(test_intrusive_timer_is_active) // { // timerInsertRemoveTest.clear(); // etl::intrusive_timer<4> timer_controller; @@ -1103,7 +1077,7 @@ namespace // } // } // - // TEST(intrusive_timer_threads) + // TEST(test_intrusive_timer_threads) // { // FIX_PROCESSOR_AFFINITY; //