Work in progress

This commit is contained in:
John Wellbelove 2026-10-21 20:58:31 +01:00
parent 024b2dd2c5
commit b903d7759e
6 changed files with 106 additions and 82 deletions

View File

@ -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

View File

@ -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;
}
//*******************************

View File

@ -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;
}

View File

@ -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());

View File

@ -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};

View File

@ -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);