diff --git a/include/etl/intrusive_timer.h b/include/etl/intrusive_timer.h index c7b24d85..2cc5ca2f 100644 --- a/include/etl/intrusive_timer.h +++ b/include/etl/intrusive_timer.h @@ -74,6 +74,7 @@ namespace etl , expired_list() , enabled(false) , timer_count(0U) + , next_id(0U) { } @@ -83,25 +84,16 @@ namespace etl //******************************************* bool register_timer(etl::timer_node& node) ETL_NOEXCEPT { - etl::timer::id::type id = node.get_id(); - bool result = false; + bool result = false; - if (id != etl::timer::id::No_Timer) - { - lock_policy.lock(); + etl::timer::id::type id = get_next_id(); + node.set_id(id); - // Remove any existing timer with the same id. - active_list.remove(id); - register_list.remove(id); + // Register the new timer. + register_list.insert(&node); - // Register the new timer. - register_list.insert(&node); - - lock_policy.unlock(); - - result = true; - ++timer_count; - } + result = true; + ++timer_count; return result; } @@ -385,6 +377,35 @@ namespace etl private: + //******************************************* + /// Gets the next available timer id. + //******************************************* + etl::timer::id::type get_next_id() ETL_NOEXCEPT + { + etl::timer::id::type next_id = 0; // IDs start at 0 + + etl::timer_node* timer = register_list.first(); + + while (timer != register_list.end()) + { + if (timer->get_id() == next_id) + { + // Already in use, so increment next_id and continue checking + ++next_id; + } + else if (timer->get_id() > next_id) + { + // Found a gap in the IDs, so return the next_id + return next_id; + } + + timer = register_list.next(timer); + } + + // We never found a gap, so return the next available ID + return next_id; + } + //******************************************* /// Stops a timer without locking. /// Returns the timer node if it was found, otherwise returns end(). @@ -446,6 +467,7 @@ namespace etl bool enabled; size_t timer_count; + etl::timer::id::type next_id; }; } // namespace etl diff --git a/include/etl/private/timer_lists.h b/include/etl/private/timer_lists.h index 387601a4..717cfca2 100644 --- a/include/etl/private/timer_lists.h +++ b/include/etl/private/timer_lists.h @@ -70,21 +70,30 @@ namespace etl } //******************************* - // Adds the timer in to the list. + // Adds the timer in to the list in ID order. //******************************* void insert(etl::timer_node* new_timer) ETL_NOEXCEPT { + new_timer->registered_next = end(); + if (empty()) { head = new_timer; } else { - tail->registered_next = new_timer; - } + etl::timer_node* current = head; + etl::timer_node* last = head; - tail = new_timer; - new_timer->registered_next = end(); + while ((current != end()) && (current->get_id() < new_timer->get_id())) + { + last = current; + current = current->registered_next; + } + + new_timer->registered_next = current; + last->registered_next = new_timer; + } } //******************************* @@ -129,10 +138,11 @@ namespace etl last->registered_next = next; } - // Clear the next pointer of the removed timer. + // Clear the id and next pointer of the removed timer. + current->set_id(etl::timer::id::No_Timer); current->registered_next = end(); - return current; + return next; } //******************************* @@ -331,7 +341,7 @@ namespace etl // Clear the next pointer of the removed timer. current->active_next = end(); - return current; + return next; } //******************************* diff --git a/include/etl/timer_node.h b/include/etl/timer_node.h index 4a10114b..af361e5e 100644 --- a/include/etl/timer_node.h +++ b/include/etl/timer_node.h @@ -69,10 +69,10 @@ namespace etl //******************************************* /// Constructor. //******************************************* - ETL_CONSTEXPR timer_config(etl::timer::id::type id_, uint32_t period_, etl::timer::mode::type repeating_) ETL_NOEXCEPT + ETL_CONSTEXPR timer_config(uint32_t period_, etl::timer::mode::type repeating_) ETL_NOEXCEPT : period(period_) , mode(repeating_) - , id(id_) + , id(etl::timer::id::No_Timer) { } @@ -223,6 +223,14 @@ namespace etl return ETL_NULLPTR; } + //******************************************* + /// Sets the ID of the timer. + //******************************************* + void set_id(etl::timer::id::type id_) ETL_NOEXCEPT + { + config.id = id_; + } + //*************************************************************************** /// Returns a reference to the sentinel timer node used to mark the end of /// the intrusive timer lists. @@ -233,7 +241,7 @@ namespace etl //*************************************************************************** static etl::timer_node* sentinal() ETL_NOEXCEPT { - static etl::timer_node sentinel_node(etl::timer_config(0, 0, 0)); + static etl::timer_node sentinel_node(etl::timer_config(0, 0)); return &sentinel_node; } diff --git a/test/test_intrusive_timer.cpp b/test/test_intrusive_timer.cpp index c35e0314..c687eb9a 100644 --- a/test/test_intrusive_timer.cpp +++ b/test/test_intrusive_timer.cpp @@ -143,9 +143,9 @@ namespace etl::intrusive_timer timer_controller(lock_policy); - etl::timer_node node1(etl::timer_config(etl::timer::id::type(1), 100, etl::timer::mode::Single_Shot)); - etl::timer_node node2(etl::timer_config(etl::timer::id::type(2), 200, etl::timer::mode::Repeating)); - etl::timer_node node3(etl::timer_config(etl::timer::id::type(3), 300, etl::timer::mode::Repeating)); + etl::timer_node node1(etl::timer_config(100, etl::timer::mode::Single_Shot)); + etl::timer_node node2(etl::timer_config(200, etl::timer::mode::Repeating)); + etl::timer_node node3(etl::timer_config(300, etl::timer::mode::Repeating)); CHECK_TRUE(timer_controller.register_timer(node1)); CHECK_EQUAL(1U, timer_controller.number_of_registered_timers()); @@ -164,9 +164,9 @@ namespace etl::intrusive_timer timer_controller(lock_policy); - etl::timer_node node1(etl::timer_config(etl::timer::id::type(1), 100, etl::timer::mode::Single_Shot)); - etl::timer_node node2(etl::timer_config(etl::timer::id::type(2), 200, etl::timer::mode::Repeating)); - etl::timer_node node3(etl::timer_config(etl::timer::id::type(3), 300, etl::timer::mode::Repeating)); + etl::timer_node node1(etl::timer_config(100, etl::timer::mode::Single_Shot)); + etl::timer_node node2(etl::timer_config(200, etl::timer::mode::Repeating)); + etl::timer_node node3(etl::timer_config(300, etl::timer::mode::Repeating)); timer_controller.register_timer(node1); timer_controller.register_timer(node2); @@ -189,9 +189,9 @@ namespace etl::intrusive_timer timer_controller(lock_policy); - etl::timer_node node1(etl::timer_config(etl::timer::id::type(1), 100, etl::timer::mode::Single_Shot)); - etl::timer_node node2(etl::timer_config(etl::timer::id::type(2), 200, etl::timer::mode::Repeating)); - etl::timer_node node3(etl::timer_config(etl::timer::id::type(3), 300, etl::timer::mode::Repeating)); + etl::timer_node node1(etl::timer_config(100, etl::timer::mode::Single_Shot)); + etl::timer_node node2(etl::timer_config(200, etl::timer::mode::Repeating)); + etl::timer_node node3(etl::timer_config(300, etl::timer::mode::Repeating)); timer_controller.register_timer(node1); timer_controller.register_timer(node2); @@ -213,23 +213,23 @@ namespace etl::intrusive_timer timer_controller(lock_policy); - etl::timer_node node1(etl::timer_config(etl::timer::id::type(1), 100, etl::timer::mode::Single_Shot)); - etl::timer_node node2(etl::timer_config(etl::timer::id::type(2), 200, etl::timer::mode::Repeating)); - etl::timer_node node3(etl::timer_config(etl::timer::id::type(3), 300, etl::timer::mode::Repeating)); + etl::timer_node node1(etl::timer_config(100, etl::timer::mode::Single_Shot)); + etl::timer_node node2(etl::timer_config(200, etl::timer::mode::Repeating)); + etl::timer_node node3(etl::timer_config(300, etl::timer::mode::Repeating)); timer_controller.register_timer(node1); timer_controller.register_timer(node2); timer_controller.register_timer(node3); // Modify the timer periods. - timer_controller.set_period(1, 150U); - timer_controller.set_period(2, 250U); - timer_controller.set_period(3, 350U); + timer_controller.set_period(node1.get_id(), 150U); + timer_controller.set_period(node2.get_id(), 250U); + timer_controller.set_period(node3.get_id(), 350U); // Modify the timer modes. - timer_controller.set_mode(1, etl::timer::mode::Repeating); - timer_controller.set_mode(2, etl::timer::mode::Single_Shot); - timer_controller.set_mode(3, etl::timer::mode::Single_Shot); + timer_controller.set_mode(node1.get_id(), etl::timer::mode::Repeating); + timer_controller.set_mode(node2.get_id(), etl::timer::mode::Single_Shot); + timer_controller.set_mode(node3.get_id(), etl::timer::mode::Single_Shot); CHECK_EQUAL(150U, node1.get_period()); CHECK_EQUAL(250U, node2.get_period()); diff --git a/test/test_timer_lists.cpp b/test/test_timer_lists.cpp index f50cc8af..5f3b842a 100644 --- a/test/test_timer_lists.cpp +++ b/test/test_timer_lists.cpp @@ -38,11 +38,11 @@ namespace //************************************************************************* TEST(test_timer_register_list) { - constexpr etl::timer_config timer1_config(1, 100, etl::timer::mode::Repeating); - constexpr etl::timer_config timer2_config(2, 65, etl::timer::mode::Repeating); - constexpr etl::timer_config timer3_config(3, 85, etl::timer::mode::Repeating); - constexpr etl::timer_config timer4_config(4, 130, etl::timer::mode::Repeating); - constexpr etl::timer_config timer5_config(5, 85, etl::timer::mode::Repeating); + constexpr etl::timer_config timer1_config(100, etl::timer::mode::Repeating); + constexpr etl::timer_config timer2_config(65, etl::timer::mode::Repeating); + constexpr etl::timer_config timer3_config(85, etl::timer::mode::Repeating); + constexpr etl::timer_config timer4_config(130, etl::timer::mode::Repeating); + constexpr etl::timer_config timer5_config(85, etl::timer::mode::Repeating); etl::timer_node timer1{timer1_config}; etl::timer_node timer2{timer2_config}; etl::timer_node timer3{timer3_config}; @@ -64,21 +64,6 @@ namespace CHECK_FALSE(register_list.empty()); CHECK_TRUE(register_list.first() == &timer1); - etl::timer_node* timer = register_list.first(); - - // The timers should be in the order they were added. - CHECK_EQUAL(&timer1, timer); - timer = register_list.next(timer); - CHECK_EQUAL(&timer2, timer); - timer = register_list.next(timer); - CHECK_EQUAL(&timer3, timer); - timer = register_list.next(timer); - CHECK_EQUAL(&timer4, timer); - timer = register_list.next(timer); - CHECK_EQUAL(&timer5, timer); - timer = register_list.next(timer); - CHECK_EQUAL(register_list.end(), timer); - // Remove timer3 from the list. register_list.remove(timer3.get_config().get_id()); @@ -89,7 +74,7 @@ namespace bool timer4_found = false; bool timer5_found = false; - timer = register_list.first(); + etl::timer_node* timer = register_list.first(); while (timer != register_list.end()) { @@ -133,12 +118,12 @@ namespace //************************************************************************* TEST(test_timer_active_list) { - constexpr etl::timer_config timer1_config(1, 100, etl::timer::mode::Repeating); - constexpr etl::timer_config timer2_config(2, 65, etl::timer::mode::Repeating); - constexpr etl::timer_config timer3_config(3, 85, etl::timer::mode::Repeating); - constexpr etl::timer_config timer4_config(4, 130, etl::timer::mode::Repeating); - constexpr etl::timer_config timer5_config(5, 85, etl::timer::mode::Repeating); - constexpr etl::timer_config timer6_config(6, 85, etl::timer::mode::Repeating); + constexpr etl::timer_config timer1_config(100, etl::timer::mode::Repeating); + constexpr etl::timer_config timer2_config(65, etl::timer::mode::Repeating); + constexpr etl::timer_config timer3_config(85, etl::timer::mode::Repeating); + constexpr etl::timer_config timer4_config(130, etl::timer::mode::Repeating); + constexpr etl::timer_config timer5_config(85, etl::timer::mode::Repeating); + constexpr etl::timer_config timer6_config(85, etl::timer::mode::Repeating); etl::timer_node timer1(timer1_config); etl::timer_node timer2(timer2_config); @@ -285,12 +270,11 @@ namespace //************************************************************************* TEST(test_timer_expired_list) { - constexpr etl::timer_config timer1_config(1, 100, etl::timer::mode::Repeating); - constexpr etl::timer_config timer2_config(2, 65, etl::timer::mode::Repeating); - constexpr etl::timer_config timer3_config(3, 85, etl::timer::mode::Repeating); - constexpr etl::timer_config timer4_config(4, 130, etl::timer::mode::Repeating); - constexpr etl::timer_config timer5_config(5, 85, etl::timer::mode::Repeating); - + constexpr etl::timer_config timer1_config(100, etl::timer::mode::Repeating); + constexpr etl::timer_config timer2_config(65, etl::timer::mode::Repeating); + constexpr etl::timer_config timer3_config(85, etl::timer::mode::Repeating); + constexpr etl::timer_config timer4_config(130, etl::timer::mode::Repeating); + constexpr etl::timer_config timer5_config(85, etl::timer::mode::Repeating); etl::timer_node timer1{timer1_config}; etl::timer_node timer2{timer2_config}; etl::timer_node timer3{timer3_config}; diff --git a/test/test_timer_node.cpp b/test/test_timer_node.cpp index f243eae9..75237df0 100644 --- a/test/test_timer_node.cpp +++ b/test/test_timer_node.cpp @@ -37,11 +37,11 @@ namespace //************************************************************************* TEST(test_timer_config) { - constexpr etl::timer_config config1(1, 100U, etl::timer::mode::Repeating); + constexpr etl::timer_config config1(100U, etl::timer::mode::Repeating); CHECK_EQUAL(100U, config1.get_period()); CHECK_EQUAL(etl::timer::mode::Repeating, config1.get_mode()); - etl::timer_config config2(2, 200U, etl::timer::mode::Single_Shot); + etl::timer_config config2(200U, etl::timer::mode::Single_Shot); CHECK_EQUAL(200U, config2.get_period()); CHECK_EQUAL(etl::timer::mode::Single_Shot, config2.get_mode()); @@ -49,7 +49,7 @@ namespace CHECK_EQUAL(config2.get_period(), config3.get_period()); CHECK_EQUAL(etl::timer::mode::Single_Shot, config2.get_mode()); - etl::timer_config config4 = etl::timer_config(4, 500U, etl::timer::mode::Repeating); + etl::timer_config config4 = etl::timer_config(500U, etl::timer::mode::Repeating); CHECK_EQUAL(500U, config4.get_period()); CHECK_EQUAL(etl::timer::mode::Repeating, config4.get_mode()); @@ -61,7 +61,7 @@ namespace //************************************************************************* TEST(test_timer_node) { - constexpr etl::timer_config config1(1, 100U, etl::timer::mode::Repeating); + constexpr etl::timer_config config1(100U, etl::timer::mode::Repeating); etl::timer_node node1(config1); etl::timer_node node2(node1);