Updated tests

Modified node end() and 'time to next' notification callback
This commit is contained in:
John Wellbelove 2026-10-25 10:55:24 +00:00
parent 28ac16f035
commit f1d188e60c
3 changed files with 447 additions and 435 deletions

View File

@ -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 <stdint.h>
@ -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<void(const etl::timer_node*)> timer_notification_callback_type;
typedef etl::delegate<void(uint32_t delta)> 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;

View File

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

View File

@ -136,19 +136,23 @@ namespace
};
//*************************************************************************
using CallbackDelegate = etl::delegate<void(const etl::timer_config&)>;
using CallbackDelegate = etl::delegate<void()>;
using CallbackTimer = etl::timer_callback_node<CallbackDelegate>;
//*************************************************************************
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<MessageProcessor, CallbackMessage>()
, 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<CallbackMessage>;
@ -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<uint32_t> 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<Object, &Object::member, object>();
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<Object, &Object::member, object>();
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<Object, &Object::member, object>();
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<Object, &Object::member, object>();
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<uint64_t> compare1 = {37, 74};
// std::vector<uint64_t> compare2 = {23, 46, 69, 92};
// std::vector<uint64_t> 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<uint64_t> compare1 = {40, 75};
// std::vector<uint64_t> compare2 = {25, 50, 70, 95};
// std::vector<uint64_t> 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<uint64_t> compare1 = {77};
// std::vector<uint64_t> compare2 = {23};
// std::vector<uint64_t> 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<uint64_t> 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<uint64_t> 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<uint64_t> compare1 = {77};
// std::vector<uint64_t> compare2 = {23};
// std::vector<uint64_t> 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_object, &test_object::call>(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;
//