Merge branch 'pull-request/#1191-Introduce-Cast-to-void-for-Condition-of-Assert' into development

# Conflicts:
#	include/etl/error_handler.h
This commit is contained in:
John Wellbelove 2025-10-02 08:15:17 +01:00
commit a9265b1a71
21 changed files with 1187 additions and 385 deletions

View File

@ -77,305 +77,6 @@ SOFTWARE.
namespace etl
{
//*************************************************************************
/// The configuration of a timer.
struct callback_timer_data
{
typedef etl::delegate<void(void)> callback_type;
enum callback_type_id
{
C_CALLBACK,
IFUNCTION,
DELEGATE
};
//*******************************************
callback_timer_data()
: p_callback(ETL_NULLPTR),
period(0),
delta(etl::timer::state::Inactive),
id(etl::timer::id::NO_TIMER),
previous(etl::timer::id::NO_TIMER),
next(etl::timer::id::NO_TIMER),
repeating(true),
cbk_type(IFUNCTION)
{
}
//*******************************************
/// C function callback
//*******************************************
callback_timer_data(etl::timer::id::type id_,
void (*p_callback_)(),
uint32_t period_,
bool repeating_)
: p_callback(reinterpret_cast<void*>(p_callback_)),
period(period_),
delta(etl::timer::state::Inactive),
id(id_),
previous(etl::timer::id::NO_TIMER),
next(etl::timer::id::NO_TIMER),
repeating(repeating_),
cbk_type(C_CALLBACK)
{
}
//*******************************************
/// ETL function callback
//*******************************************
callback_timer_data(etl::timer::id::type id_,
etl::ifunction<void>& callback_,
uint32_t period_,
bool repeating_)
: p_callback(reinterpret_cast<void*>(&callback_)),
period(period_),
delta(etl::timer::state::Inactive),
id(id_),
previous(etl::timer::id::NO_TIMER),
next(etl::timer::id::NO_TIMER),
repeating(repeating_),
cbk_type(IFUNCTION)
{
}
//*******************************************
/// ETL delegate callback
//*******************************************
callback_timer_data(etl::timer::id::type id_,
callback_type& callback_,
uint32_t period_,
bool repeating_)
: p_callback(reinterpret_cast<void*>(&callback_)),
period(period_),
delta(etl::timer::state::Inactive),
id(id_),
previous(etl::timer::id::NO_TIMER),
next(etl::timer::id::NO_TIMER),
repeating(repeating_),
cbk_type(DELEGATE)
{
}
//*******************************************
/// Returns true if the timer is active.
//*******************************************
bool is_active() const
{
return delta != etl::timer::state::Inactive;
}
//*******************************************
/// Sets the timer to the inactive state.
//*******************************************
void set_inactive()
{
delta = etl::timer::state::Inactive;
}
void* p_callback;
uint32_t period;
uint32_t delta;
etl::timer::id::type id;
uint_least8_t previous;
uint_least8_t next;
bool repeating;
callback_type_id cbk_type;
private:
// Disabled.
callback_timer_data(const callback_timer_data& other);
callback_timer_data& operator =(const callback_timer_data& other);
};
namespace private_callback_timer
{
//*************************************************************************
/// A specialised intrusive linked list for timer data.
//*************************************************************************
class list
{
public:
//*******************************
list(etl::callback_timer_data* ptimers_)
: head(etl::timer::id::NO_TIMER),
tail(etl::timer::id::NO_TIMER),
current(etl::timer::id::NO_TIMER),
ptimers(ptimers_)
{
}
//*******************************
bool empty() const
{
return head == etl::timer::id::NO_TIMER;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
void insert(etl::timer::id::type id_)
{
etl::callback_timer_data& timer = ptimers[id_];
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
head = id_;
tail = id_;
timer.previous = etl::timer::id::NO_TIMER;
timer.next = etl::timer::id::NO_TIMER;
}
else
{
// We already have entries.
etl::timer::id::type test_id = begin();
while (test_id != etl::timer::id::NO_TIMER)
{
etl::callback_timer_data& test = ptimers[test_id];
// Find the correct place to insert.
if (timer.delta <= test.delta)
{
if (test.id == head)
{
head = timer.id;
}
// Insert before test.
timer.previous = test.previous;
test.previous = timer.id;
timer.next = test.id;
// Adjust the next delta to compensate.
test.delta -= timer.delta;
if (timer.previous != etl::timer::id::NO_TIMER)
{
ptimers[timer.previous].next = timer.id;
}
break;
}
else
{
timer.delta -= test.delta;
}
test_id = next(test_id);
}
// Reached the end?
if (test_id == etl::timer::id::NO_TIMER)
{
// Tag on to the tail.
ptimers[tail].next = timer.id;
timer.previous = tail;
timer.next = etl::timer::id::NO_TIMER;
tail = timer.id;
}
}
}
//*******************************
void remove(etl::timer::id::type id_, bool has_expired)
{
etl::callback_timer_data& timer = ptimers[id_];
if (head == id_)
{
head = timer.next;
}
else
{
ptimers[timer.previous].next = timer.next;
}
if (tail == id_)
{
tail = timer.previous;
}
else
{
ptimers[timer.next].previous = timer.previous;
}
if (!has_expired)
{
// Adjust the next delta.
if (timer.next != etl::timer::id::NO_TIMER)
{
ptimers[timer.next].delta += timer.delta;
}
}
timer.previous = etl::timer::id::NO_TIMER;
timer.next = etl::timer::id::NO_TIMER;
timer.delta = etl::timer::state::Inactive;
}
//*******************************
etl::callback_timer_data& front()
{
return ptimers[head];
}
//*******************************
const etl::callback_timer_data& front() const
{
return ptimers[head];
}
//*******************************
etl::timer::id::type begin()
{
current = head;
return current;
}
//*******************************
etl::timer::id::type previous(etl::timer::id::type last)
{
current = ptimers[last].previous;
return current;
}
//*******************************
etl::timer::id::type next(etl::timer::id::type last)
{
current = ptimers[last].next;
return current;
}
//*******************************
void clear()
{
etl::timer::id::type id = begin();
while (id != etl::timer::id::NO_TIMER)
{
etl::callback_timer_data& timer = ptimers[id];
id = next(id);
timer.next = etl::timer::id::NO_TIMER;
}
head = etl::timer::id::NO_TIMER;
tail = etl::timer::id::NO_TIMER;
current = etl::timer::id::NO_TIMER;
}
private:
etl::timer::id::type head;
etl::timer::id::type tail;
etl::timer::id::type current;
etl::callback_timer_data* const ptimers;
};
}
//***************************************************************************
/// Interface for callback timer
//***************************************************************************
@ -385,6 +86,8 @@ namespace etl
typedef etl::delegate<void(void)> callback_type;
typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
//*******************************************
/// Register a timer.
//*******************************************
@ -401,12 +104,12 @@ namespace etl
// Search for the free space.
for (uint_least8_t i = 0U; i < MAX_TIMERS; ++i)
{
etl::callback_timer_data& timer = timer_array[i];
timer_data& timer = timer_array[i];
if (timer.id == etl::timer::id::NO_TIMER)
{
// Create in-place.
new (&timer) callback_timer_data(i, p_callback_, period_, repeating_);
new (&timer) timer_data(i, p_callback_, period_, repeating_);
++registered_timers;
id = i;
break;
@ -433,12 +136,12 @@ namespace etl
// Search for the free space.
for (uint_least8_t i = 0U; i < MAX_TIMERS; ++i)
{
etl::callback_timer_data& timer = timer_array[i];
timer_data& timer = timer_array[i];
if (timer.id == etl::timer::id::NO_TIMER)
{
// Create in-place.
new (&timer) callback_timer_data(i, callback_, period_, repeating_);
new (&timer) timer_data(i, callback_, period_, repeating_);
++registered_timers;
id = i;
break;
@ -466,12 +169,12 @@ namespace etl
// Search for the free space.
for (uint_least8_t i = 0U; i < MAX_TIMERS; ++i)
{
etl::callback_timer_data& timer = timer_array[i];
timer_data& timer = timer_array[i];
if (timer.id == etl::timer::id::NO_TIMER)
{
// Create in-place.
new (&timer) callback_timer_data(i, callback_, period_, repeating_);
new (&timer) timer_data(i, callback_, period_, repeating_);
++registered_timers;
id = i;
break;
@ -492,7 +195,7 @@ namespace etl
if (id_ != etl::timer::id::NO_TIMER)
{
etl::callback_timer_data& timer = timer_array[id_];
timer_data& timer = timer_array[id_];
if (timer.id != etl::timer::id::NO_TIMER)
{
@ -500,11 +203,12 @@ namespace etl
{
ETL_DISABLE_TIMER_UPDATES;
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
ETL_ENABLE_TIMER_UPDATES;
}
// Reset in-place.
new (&timer) callback_timer_data();
new (&timer) timer_data();
--registered_timers;
result = true;
@ -541,7 +245,7 @@ namespace etl
for (int i = 0; i < MAX_TIMERS; ++i)
{
::new (&timer_array[i]) callback_timer_data();
::new (&timer_array[i]) timer_data();
}
registered_timers = 0;
@ -566,32 +270,34 @@ namespace etl
{
while (has_active && (count >= active_list.front().delta))
{
etl::callback_timer_data& timer = active_list.front();
timer_data& timer = active_list.front();
count -= timer.delta;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.repeating)
{
// Reinsert the timer.
timer.delta = timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
}
if (timer.p_callback != ETL_NULLPTR)
{
if (timer.cbk_type == callback_timer_data::C_CALLBACK)
if (timer.cbk_type == timer_data::C_CALLBACK)
{
// Call the C callback.
reinterpret_cast<void(*)()>(timer.p_callback)();
}
else if(timer.cbk_type == callback_timer_data::IFUNCTION)
else if(timer.cbk_type == timer_data::IFUNCTION)
{
// Call the function wrapper callback.
(*reinterpret_cast<etl::ifunction<void>*>(timer.p_callback))();
}
else if(timer.cbk_type == callback_timer_data::DELEGATE)
else if(timer.cbk_type == timer_data::DELEGATE)
{
// Call the delegate callback.
(*reinterpret_cast<callback_type*>(timer.p_callback))();
@ -625,7 +331,7 @@ namespace etl
// Valid timer id?
if (id_ != etl::timer::id::NO_TIMER)
{
etl::callback_timer_data& timer = timer_array[id_];
timer_data& timer = timer_array[id_];
// Registered timer?
if (timer.id != etl::timer::id::NO_TIMER)
@ -637,10 +343,12 @@ namespace etl
if (timer.is_active())
{
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
timer.delta = immediate_ ? 0 : timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
ETL_ENABLE_TIMER_UPDATES;
result = true;
@ -661,7 +369,7 @@ namespace etl
// Valid timer id?
if (id_ != etl::timer::id::NO_TIMER)
{
etl::callback_timer_data& timer = timer_array[id_];
timer_data& timer = timer_array[id_];
// Registered timer?
if (timer.id != etl::timer::id::NO_TIMER)
@ -670,6 +378,7 @@ namespace etl
{
ETL_DISABLE_TIMER_UPDATES;
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
ETL_ENABLE_TIMER_UPDATES;
}
@ -743,7 +452,7 @@ namespace etl
{
if (has_active_timer())
{
const etl::callback_timer_data& timer = timer_array[id_];
const timer_data& timer = timer_array[id_];
// Registered timer?
if (timer.id != etl::timer::id::NO_TIMER)
@ -756,12 +465,152 @@ namespace etl
return false;
}
//*******************************************
/// Set a callback when a timer is inserted on list
//*******************************************
void set_insert_callback(event_callback_type insert_)
{
insert_callback = insert_;
}
//*******************************************
/// Set a callback when a timer is removed from list
//*******************************************
void set_remove_callback(event_callback_type remove_)
{
remove_callback = remove_;
}
//*******************************************
void clear_insert_callback()
{
insert_callback.clear();
}
//*******************************************
void clear_remove_callback()
{
remove_callback.clear();
}
protected:
//*************************************************************************
/// The configuration of a timer.
struct timer_data
{
typedef etl::delegate<void(void)> callback_type;
enum callback_type_id
{
C_CALLBACK,
IFUNCTION,
DELEGATE
};
//*******************************************
timer_data()
: p_callback(ETL_NULLPTR)
, period(0)
, delta(etl::timer::state::Inactive)
, id(etl::timer::id::NO_TIMER)
, previous(etl::timer::id::NO_TIMER)
, next(etl::timer::id::NO_TIMER)
, repeating(true)
, cbk_type(IFUNCTION)
{
}
//*******************************************
/// C function callback
//*******************************************
timer_data(etl::timer::id::type id_,
void (*p_callback_)(),
uint32_t period_,
bool repeating_)
: p_callback(reinterpret_cast<void*>(p_callback_))
, period(period_)
, delta(etl::timer::state::Inactive)
, id(id_)
, previous(etl::timer::id::NO_TIMER)
, next(etl::timer::id::NO_TIMER)
, repeating(repeating_)
, cbk_type(C_CALLBACK)
{
}
//*******************************************
/// ETL function callback
//*******************************************
timer_data(etl::timer::id::type id_,
etl::ifunction<void>& callback_,
uint32_t period_,
bool repeating_)
: p_callback(reinterpret_cast<void*>(&callback_))
, period(period_)
, delta(etl::timer::state::Inactive)
, id(id_)
, previous(etl::timer::id::NO_TIMER)
, next(etl::timer::id::NO_TIMER)
, repeating(repeating_)
, cbk_type(IFUNCTION)
{
}
//*******************************************
/// ETL delegate callback
//*******************************************
timer_data(etl::timer::id::type id_,
callback_type& callback_,
uint32_t period_,
bool repeating_)
: p_callback(reinterpret_cast<void*>(&callback_)),
period(period_),
delta(etl::timer::state::Inactive),
id(id_),
previous(etl::timer::id::NO_TIMER),
next(etl::timer::id::NO_TIMER),
repeating(repeating_),
cbk_type(DELEGATE)
{
}
//*******************************************
/// Returns true if the timer is active.
//*******************************************
bool is_active() const
{
return delta != etl::timer::state::Inactive;
}
//*******************************************
/// Sets the timer to the inactive state.
//*******************************************
void set_inactive()
{
delta = etl::timer::state::Inactive;
}
void* p_callback;
uint32_t period;
uint32_t delta;
etl::timer::id::type id;
uint_least8_t previous;
uint_least8_t next;
bool repeating;
callback_type_id cbk_type;
private:
// Disabled.
timer_data(const timer_data& other);
timer_data& operator =(const timer_data& other);
};
//*******************************************
/// Constructor.
//*******************************************
icallback_timer(callback_timer_data* const timer_array_, const uint_least8_t Max_Timers_)
icallback_timer(timer_data* const timer_array_, const uint_least8_t Max_Timers_)
: timer_array(timer_array_),
active_list(timer_array_),
enabled(false),
@ -783,11 +632,193 @@ namespace etl
return (id_ < MAX_TIMERS);
}
//*************************************************************************
class timer_list
{
public:
//*******************************
timer_list(timer_data* ptimers_)
: head(etl::timer::id::NO_TIMER)
, tail(etl::timer::id::NO_TIMER)
, current(etl::timer::id::NO_TIMER)
, ptimers(ptimers_)
{
}
//*******************************
bool empty() const
{
return head == etl::timer::id::NO_TIMER;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
void insert(etl::timer::id::type id_)
{
timer_data& timer = ptimers[id_];
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
head = id_;
tail = id_;
timer.previous = etl::timer::id::NO_TIMER;
timer.next = etl::timer::id::NO_TIMER;
}
else
{
// We already have entries.
etl::timer::id::type test_id = begin();
while (test_id != etl::timer::id::NO_TIMER)
{
timer_data& test = ptimers[test_id];
// Find the correct place to insert.
if (timer.delta <= test.delta)
{
if (test.id == head)
{
head = timer.id;
}
// Insert before test.
timer.previous = test.previous;
test.previous = timer.id;
timer.next = test.id;
// Adjust the next delta to compensate.
test.delta -= timer.delta;
if (timer.previous != etl::timer::id::NO_TIMER)
{
ptimers[timer.previous].next = timer.id;
}
break;
}
else
{
timer.delta -= test.delta;
}
test_id = next(test_id);
}
// Reached the end?
if (test_id == etl::timer::id::NO_TIMER)
{
// Tag on to the tail.
ptimers[tail].next = timer.id;
timer.previous = tail;
timer.next = etl::timer::id::NO_TIMER;
tail = timer.id;
}
}
}
//*******************************
void remove(etl::timer::id::type id_, bool has_expired)
{
timer_data& timer = ptimers[id_];
if (head == id_)
{
head = timer.next;
}
else
{
ptimers[timer.previous].next = timer.next;
}
if (tail == id_)
{
tail = timer.previous;
}
else
{
ptimers[timer.next].previous = timer.previous;
}
if (!has_expired)
{
// Adjust the next delta.
if (timer.next != etl::timer::id::NO_TIMER)
{
ptimers[timer.next].delta += timer.delta;
}
}
timer.previous = etl::timer::id::NO_TIMER;
timer.next = etl::timer::id::NO_TIMER;
timer.delta = etl::timer::state::Inactive;
}
//*******************************
timer_data& front()
{
return ptimers[head];
}
//*******************************
const timer_data& front() const
{
return ptimers[head];
}
//*******************************
etl::timer::id::type begin()
{
current = head;
return current;
}
//*******************************
etl::timer::id::type previous(etl::timer::id::type last)
{
current = ptimers[last].previous;
return current;
}
//*******************************
etl::timer::id::type next(etl::timer::id::type last)
{
current = ptimers[last].next;
return current;
}
//*******************************
void clear()
{
etl::timer::id::type id = begin();
while (id != etl::timer::id::NO_TIMER)
{
timer_data& timer = ptimers[id];
id = next(id);
timer.next = etl::timer::id::NO_TIMER;
}
head = etl::timer::id::NO_TIMER;
tail = etl::timer::id::NO_TIMER;
current = etl::timer::id::NO_TIMER;
}
private:
etl::timer::id::type head;
etl::timer::id::type tail;
etl::timer::id::type current;
timer_data* const ptimers;
};
// The array of timer data structures.
callback_timer_data* const timer_array;
timer_data* const timer_array;
// The list of active timers.
private_callback_timer::list active_list;
timer_list active_list;
volatile bool enabled;
#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK)
@ -806,6 +837,9 @@ namespace etl
#endif
uint_least8_t registered_timers;
event_callback_type insert_callback;
event_callback_type remove_callback;
public:
const uint_least8_t MAX_TIMERS;
@ -831,7 +865,7 @@ namespace etl
private:
callback_timer_data timer_array[Max_Timers_];
timer_data timer_array[Max_Timers_];
};
}

View File

@ -53,6 +53,8 @@ namespace etl
typedef etl::delegate<void(void)> callback_type;
typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
//*******************************************
/// Register a timer.
//*******************************************
@ -102,6 +104,7 @@ namespace etl
{
++process_semaphore;
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
--process_semaphore;
}
@ -173,6 +176,7 @@ namespace etl
count -= timer.delta;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.callback.is_valid())
{
@ -185,6 +189,7 @@ namespace etl
// Reinsert the timer.
timer.delta = timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
}
has_active = !active_list.empty();
@ -226,10 +231,12 @@ namespace etl
if (timer.is_active())
{
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
timer.delta = immediate_ ? 0U : timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
--process_semaphore;
result = true;
@ -259,6 +266,7 @@ namespace etl
{
++process_semaphore;
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
--process_semaphore;
}
@ -355,6 +363,34 @@ namespace etl
return result;
}
//*******************************************
/// Set a callback when a timer is inserted on list
//*******************************************
void set_insert_callback(event_callback_type insert_)
{
insert_callback = insert_;
}
//*******************************************
/// Set a callback when a timer is removed from list
//*******************************************
void set_remove_callback(event_callback_type remove_)
{
remove_callback = remove_;
}
//*******************************************
void clear_insert_callback()
{
insert_callback.clear();
}
//*******************************************
void clear_remove_callback()
{
remove_callback.clear();
}
protected:
//*************************************************************************
@ -638,6 +674,9 @@ namespace etl
mutable TSemaphore process_semaphore;
uint_least8_t number_of_registered_timers;
event_callback_type insert_callback;
event_callback_type remove_callback;
public:
const uint_least8_t Max_Timers;

View File

@ -54,22 +54,7 @@ namespace etl
private:
class CallbackNode
{
public:
CallbackNode(callback_type &callback_,uint_least8_t priority_) : callback(callback_), priority(priority_)
{
}
bool operator < (const CallbackNode& p) const
{
return this->priority > p.priority; // comparison was inverted here to easy the code design
}
callback_type callback;
uint_least8_t priority;
};
typedef icallback_timer_locked::callback_node callback_node;
public:
@ -111,12 +96,13 @@ namespace etl
count -= timer.delta;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.callback.is_valid())
{
if (!handler_queue.full())
{
handler_queue.push(CallbackNode(timer.callback, timer_priorities[timer.id]));
handler_queue.push(callback_node(timer.callback, timer_priorities[timer.id]));
}
}
@ -125,6 +111,7 @@ namespace etl
// Reinsert the timer.
timer.delta = timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
}
has_active = !active_list.empty();
@ -165,7 +152,7 @@ namespace etl
}
else
{
CallbackNode &work_todo_callback_node = handler_queue.top();
callback_node &work_todo_callback_node = handler_queue.top();
work_todo_callback = work_todo_callback_node.callback;
handler_queue.pop();
}
@ -211,7 +198,7 @@ namespace etl
private:
priority_queue<CallbackNode, Max_Handlers_> handler_queue;
priority_queue<callback_node, Max_Handlers_> handler_queue;
uint_least8_t timer_priorities[Max_Timers_];
timer_data timer_array[Max_Timers_];
};

View File

@ -52,6 +52,8 @@ namespace etl
typedef etl::delegate<void(void)> callback_type;
typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
//*******************************************
/// Register a timer.
//*******************************************
@ -106,6 +108,7 @@ namespace etl
(void)guard; // Silence 'unused variable warnings.
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
// Reset in-place.
@ -176,6 +179,7 @@ namespace etl
count -= timer.delta;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.callback.is_valid())
{
@ -187,6 +191,7 @@ namespace etl
// Reinsert the timer.
timer.delta = timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
}
has_active = !active_list.empty();
@ -229,10 +234,12 @@ namespace etl
if (timer.is_active())
{
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
timer.delta = immediate_ ? 0U : timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
result = true;
}
@ -263,6 +270,7 @@ namespace etl
(void)guard; // Silence 'unused variable warnings.
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
result = true;
@ -356,6 +364,34 @@ namespace etl
return false;
}
//*******************************************
/// Set a callback when a timer is inserted on list
//*******************************************
void set_insert_callback(event_callback_type insert_)
{
insert_callback = insert_;
}
//*******************************************
/// Set a callback when a timer is removed from list
//*******************************************
void set_remove_callback(event_callback_type remove_)
{
remove_callback = remove_;
}
//*******************************************
void clear_insert_callback()
{
insert_callback.clear();
}
//*******************************************
void clear_remove_callback()
{
remove_callback.clear();
}
protected:
//*************************************************************************
@ -637,6 +673,9 @@ namespace etl
bool enabled;
uint_least8_t number_of_registered_timers;
event_callback_type insert_callback;
event_callback_type remove_callback;
public:
const uint_least8_t Max_Timers;

View File

@ -54,6 +54,8 @@ namespace etl
typedef etl::delegate<void(void)> lock_type;
typedef etl::delegate<void(void)> unlock_type;
typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
//*******************************************
/// Register a timer.
//*******************************************
@ -103,6 +105,7 @@ namespace etl
{
lock();
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
unlock();
}
@ -180,10 +183,12 @@ namespace etl
if (timer.is_active())
{
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
timer.delta = immediate_ ? 0U : timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
unlock();
result = true;
@ -213,6 +218,7 @@ namespace etl
{
lock();
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
unlock();
}
@ -319,8 +325,53 @@ namespace etl
return result;
}
//*******************************************
/// Set a callback when a timer is inserted on list
//*******************************************
void set_insert_callback(event_callback_type insert_)
{
insert_callback = insert_;
}
//*******************************************
/// Set a callback when a timer is removed from list
//*******************************************
void set_remove_callback(event_callback_type remove_)
{
remove_callback = remove_;
}
//*******************************************
void clear_insert_callback()
{
insert_callback.clear();
}
//*******************************************
void clear_remove_callback()
{
remove_callback.clear();
}
protected:
class callback_node
{
public:
callback_node(callback_type &callback_,uint_least8_t priority_) : callback(callback_), priority(priority_)
{
}
bool operator < (const callback_node& p) const
{
return this->priority > p.priority; // comparison was inverted here to easy the code design
}
callback_type callback;
uint_least8_t priority;
};
//*************************************************************************
/// The configuration of a timer.
struct timer_data
@ -604,7 +655,11 @@ namespace etl
lock_type lock; ///< The callback that locks.
unlock_type unlock; ///< The callback that unlocks.
event_callback_type insert_callback;
event_callback_type remove_callback;
public:
template <uint_least8_t>
friend class callback_timer_locked;
@ -629,6 +684,12 @@ namespace etl
typedef icallback_timer_locked::lock_type lock_type;
typedef icallback_timer_locked::unlock_type unlock_type;
private:
typedef icallback_timer_locked::callback_node callback_node;
public:
//*******************************************
/// Constructor.
//*******************************************
@ -646,8 +707,9 @@ namespace etl
this->set_locks(try_lock_, lock_, unlock_);
}
// Implement virtual functions
//*******************************************
/// Handle the tick call
//*******************************************
bool tick(uint32_t count) final
{
if (enabled)
@ -666,6 +728,7 @@ namespace etl
count -= timer.delta;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.callback.is_valid())
{
@ -677,6 +740,7 @@ namespace etl
// Reinsert the timer.
timer.delta = timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
}
has_active = !active_list.empty();

View File

@ -301,65 +301,65 @@ namespace etl
///\ingroup error_handler
//***************************************************************************
#if defined(ETL_NO_CHECKS)
#define ETL_ASSERT(b, e) ETL_DO_NOTHING // Does nothing.
#define ETL_ASSERT_OR_RETURN(b, e) ETL_DO_NOTHING // Does nothing.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) ETL_DO_NOTHING // Does nothing.
#define ETL_ASSERT(b, e) static_cast<void>(sizeof(b)) // Does nothing.
#define ETL_ASSERT_OR_RETURN(b, e) static_cast<void>(sizeof(b)) // Does nothing.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) static_cast<void>(sizeof(b)) // Does nothing.
#define ETL_ASSERT_FAIL(e) ETL_DO_NOTHING // Does nothing.
#define ETL_ASSERT_FAIL_AND_RETURN(e) ETL_DO_NOTHING // Does nothing.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) ETL_DO_NOTHING // Does nothing.
#define ETL_ASSERT_FAIL(e) static_cast<void>(sizeof(b)) // Does nothing.
#define ETL_ASSERT_FAIL_AND_RETURN(e) static_cast<void>(sizeof(b)) // Does nothing.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) static_cast<void>(sizeof(b)) // Does nothing.
#elif defined(ETL_USE_ASSERT_FUNCTION)
#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));}} // If the condition fails, calls the assert function
#define ETL_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return;}} // If the condition fails, calls the assert function and return
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return (v);}} // If the condition fails, calls the assert function and return a value
#define ETL_ASSERT(b, e) do {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));}} while(false) // If the condition fails, calls the assert function
#define ETL_ASSERT_OR_RETURN(b, e) do {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return;}} while(false) // If the condition fails, calls the assert function and return
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) do {if (!(b)) ETL_UNLIKELY {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return (v);}} while(false) // If the condition fails, calls the assert function and return a value
#define ETL_ASSERT_FAIL(e) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));} // Calls the assert function
#define ETL_ASSERT_FAIL_AND_RETURN(e) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return;} // Calls the assert function and return
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return (v);} // Calls the assert function and return a value
#define ETL_ASSERT_FAIL(e) do {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e));} while(false) // Calls the assert function
#define ETL_ASSERT_FAIL_AND_RETURN(e) do {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return;} while(false) // Calls the assert function and return
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) do {etl::private_error_handler::assert_handler<0>::assert_function_ptr((e)); return (v);} while(false) // Calls the assert function and return a value
#elif ETL_USING_EXCEPTIONS
#if defined(ETL_LOG_ERRORS)
#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e));}} // If the condition fails, calls the error handler then throws an exception.
#define ETL_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e)); return;}} // If the condition fails, calls the error handler then throws an exception.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e)); return(v);}} // If the condition fails, calls the error handler then throws an exception.
#define ETL_ASSERT(b, e) do {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e));}} while(false) // If the condition fails, calls the error handler then throws an exception.
#define ETL_ASSERT_OR_RETURN(b, e) do {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e)); return;}} while(false) // If the condition fails, calls the error handler then throws an exception.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) do {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e)); return(v);}} while(false) // If the condition fails, calls the error handler then throws an exception.
#define ETL_ASSERT_FAIL(e) {etl::error_handler::error((e)); throw((e));} // Calls the error handler then throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN(e) {etl::error_handler::error((e)); throw((e)); return;} // Calls the error handler then throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {etl::error_handler::error((e)); throw((e)); return(v);} // Calls the error handler then throws an exception.
#define ETL_ASSERT_FAIL(e) do {etl::error_handler::error((e)); throw((e));} while(false) // Calls the error handler then throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN(e) do {etl::error_handler::error((e)); throw((e)); return;} while(false) // Calls the error handler then throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) do {etl::error_handler::error((e)); throw((e)); return(v);} while(false) // Calls the error handler then throws an exception.
#else
#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {throw((e));}} // If the condition fails, throws an exception.
#define ETL_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {throw((e));}} // If the condition fails, throws an exception.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {throw((e));}} // If the condition fails, throws an exception.
#define ETL_ASSERT(b, e) do {if (!(b)) ETL_UNLIKELY {throw((e));}} while(false) // If the condition fails, throws an exception.
#define ETL_ASSERT_OR_RETURN(b, e) do {if (!(b)) ETL_UNLIKELY {throw((e));}} while(false) // If the condition fails, throws an exception.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) do {if (!(b)) ETL_UNLIKELY {throw((e));}} while(false) // If the condition fails, throws an exception.
#define ETL_ASSERT_FAIL(e) {throw((e));} // Throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN(e) {throw((e));} // Throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {throw((e));} // Throws an exception.
#define ETL_ASSERT_FAIL(e) do {throw((e));} while(false) // Throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN(e) do {throw((e));} while(false) // Throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) do {throw((e));} while(false) // Throws an exception.
#endif
#else
#if defined(ETL_LOG_ERRORS)
#define ETL_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e));}} // If the condition fails, calls the error handler
#define ETL_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); return;}} // If the condition fails, calls the error handler and return
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); return (v);}} // If the condition fails, calls the error handler and return a value
#define ETL_ASSERT(b, e) do {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e));}} while(false) // If the condition fails, calls the error handler
#define ETL_ASSERT_OR_RETURN(b, e) do {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); return;}} while(false) // If the condition fails, calls the error handler and return
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) do {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); return (v);}} while(false) // If the condition fails, calls the error handler and return a value
#define ETL_ASSERT_FAIL(e) {etl::error_handler::error((e));} // Calls the error handler
#define ETL_ASSERT_FAIL_AND_RETURN(e) {etl::error_handler::error((e)); return;} // Calls the error handler and return
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {etl::error_handler::error((e)); return (v);} // Calls the error handler and return a value
#define ETL_ASSERT_FAIL(e) do {etl::error_handler::error((e));} while(false) // Calls the error handler
#define ETL_ASSERT_FAIL_AND_RETURN(e) do {etl::error_handler::error((e)); return;} while(false) // Calls the error handler and return
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) do {etl::error_handler::error((e)); return (v);} while(false) // Calls the error handler and return a value
#else
#if ETL_IS_DEBUG_BUILD
#define ETL_ASSERT(b, e) assert((b)) // If the condition fails, asserts.
#define ETL_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {assert(false); return;}} // If the condition fails, asserts and return.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {assert(false); return(v);}} // If the condition fails, asserts and return a value.
#define ETL_ASSERT(b, e) assert((b)) // If the condition fails, asserts.
#define ETL_ASSERT_OR_RETURN(b, e) do {if (!(b)) ETL_UNLIKELY {assert(false); return;}} while(false) // If the condition fails, asserts and return.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) do {if (!(b)) ETL_UNLIKELY {assert(false); return(v);}} while(false) // If the condition fails, asserts and return a value.
#define ETL_ASSERT_FAIL(e) assert(false) // Asserts.
#define ETL_ASSERT_FAIL_AND_RETURN(e) {assert(false); return;} // Asserts.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {assert(false); return(v);} // Asserts.
#define ETL_ASSERT_FAIL(e) assert(false) // Asserts.
#define ETL_ASSERT_FAIL_AND_RETURN(e) do {assert(false); return;} while(false) // Asserts.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) do {assert(false); return(v);} while(false) // Asserts.
#else
#define ETL_ASSERT(b, e) // Does nothing.
#define ETL_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY return;} // Returns.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY return(v);} // Returns a value.
#define ETL_ASSERT(b, e) static_cast<void>(sizeof(b)) // Does nothing.
#define ETL_ASSERT_OR_RETURN(b, e) do {if (!(b)) ETL_UNLIKELY return;} while(false) // Returns.
#define ETL_ASSERT_OR_RETURN_VALUE(b, e, v) do {if (!(b)) ETL_UNLIKELY return(v);} while(false) // Returns a value.
#define ETL_ASSERT_FAIL(e) // Does nothing.
#define ETL_ASSERT_FAIL_AND_RETURN(e) {return;} // Returns.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {return(v);} // Returns a value.
#define ETL_ASSERT_FAIL(e) ETL_DO_NOTHING // Does nothing.
#define ETL_ASSERT_FAIL_AND_RETURN(e) do {return;} while(false) // Returns.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) do {return(v);} while(false) // Returns a value.
#endif
#endif
#endif
@ -376,7 +376,6 @@ namespace etl
#elif ETL_DEBUG_USING_EXCEPTIONS
#if defined(ETL_DEBUG_LOG_ERRORS)
#define ETL_DEBUG_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e));}} // If the condition fails, calls the error handler then throws an exception.
#define ETL_DEBUG_ASSERT_OR_RETURN_VALUE_CPP11_CONSTEXPR(b, e, v) if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e));} return (b) ? (v) : throw(e) // throwing from c++11 constexpr requires ? operator
#define ETL_DEBUG_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e)); return;}} // If the condition fails, calls the error handler then throws an exception.
#define ETL_DEBUG_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {etl::error_handler::error((e)); throw((e)); return(v);}} // If the condition fails, calls the error handler then throws an exception.
@ -385,7 +384,6 @@ namespace etl
#define ETL_DEBUG_ASSERT_FAIL_AND_RETURN_VALUE(e, v) {etl::error_handler::error((e)); throw((e)); return(v);} // Calls the error handler then throws an exception.
#else
#define ETL_DEBUG_ASSERT(b, e) {if (!(b)) ETL_UNLIKELY {throw((e));}} // If the condition fails, throws an exception.
#define ETL_DEBUG_ASSERT_OR_RETURN_VALUE_CPP11_CONSTEXPR(b, e, v) return (b) ? (v) : throw(e) // throwing from c++11 constexpr requires ? operator
#define ETL_DEBUG_ASSERT_OR_RETURN(b, e) {if (!(b)) ETL_UNLIKELY {throw((e));}} // If the condition fails, throws an exception.
#define ETL_DEBUG_ASSERT_OR_RETURN_VALUE(b, e, v) {if (!(b)) ETL_UNLIKELY {throw((e));}} // If the condition fails, throws an exception.
@ -448,10 +446,12 @@ namespace etl
#define ETL_ERROR(e) (e(__FILE__, __LINE__)) // Make an exception with the file name and line number.
#define ETL_ERROR_WITH_VALUE(e, v) (e(__FILE__, __LINE__, (v))) // Make an exception with the file name, line number and value.
#define ETL_ERROR_TEXT(verbose_text, terse_text) (verbose_text) // Use the verbose text.
#define ETL_ERROR_UNTYPED(text) (etl::exception((text),__FILE__,__LINE__)) // Make a generic exception with a message, file name and line number.
#else
#define ETL_ERROR(e) (e("", __LINE__)) // Make an exception with the line number.
#define ETL_ERROR_WITH_VALUE(e, v) (e("", __LINE__, (v))) // Make an exception with the file name, line number and value.
#define ETL_ERROR_TEXT(verbose_text, terse_text) (terse_text) // Use the terse text.
#define ETL_ERROR_UNTYPED(text) (etl::exception((text),"",__LINE__)) // Make a generic exception with a message and line number.
#endif
#endif

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include "timer.h"
#include "atomic.h"
#include "algorithm.h"
#include "delegate.h"
#include <stdint.h>
@ -341,6 +342,8 @@ namespace etl
{
public:
typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
//*******************************************
/// Register a timer.
//*******************************************
@ -396,6 +399,7 @@ namespace etl
{
ETL_DISABLE_TIMER_UPDATES;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
ETL_ENABLE_TIMER_UPDATES;
}
@ -467,11 +471,13 @@ namespace etl
count -= timer.delta;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.repeating)
{
timer.delta = timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
}
if (timer.p_router != ETL_NULLPTR)
@ -518,10 +524,12 @@ namespace etl
if (timer.is_active())
{
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
timer.delta = immediate_ ? 0 : timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
ETL_ENABLE_TIMER_UPDATES;
result = true;
@ -551,6 +559,7 @@ namespace etl
{
ETL_DISABLE_TIMER_UPDATES;
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
ETL_ENABLE_TIMER_UPDATES;
}
@ -619,6 +628,34 @@ namespace etl
return delta;
}
//*******************************************
/// Set a callback when a timer is inserted on list
//*******************************************
void set_insert_callback(event_callback_type insert_)
{
insert_callback = insert_;
}
//*******************************************
/// Set a callback when a timer is removed from list
//*******************************************
void set_remove_callback(event_callback_type remove_)
{
remove_callback = remove_;
}
//*******************************************
void clear_insert_callback()
{
insert_callback.clear();
}
//*******************************************
void clear_remove_callback()
{
remove_callback.clear();
}
protected:
//*******************************************
@ -669,6 +706,9 @@ namespace etl
#endif
uint_least8_t registered_timers;
event_callback_type insert_callback;
event_callback_type remove_callback;
public:
const uint_least8_t Max_Timers;

View File

@ -39,6 +39,7 @@ SOFTWARE.
#include "timer.h"
#include "atomic.h"
#include "algorithm.h"
#include "delegate.h"
#include <stdint.h>
@ -54,6 +55,8 @@ namespace etl
{
public:
typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
//*******************************************
/// Register a timer.
//*******************************************
@ -109,6 +112,7 @@ namespace etl
{
++process_semaphore;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
--process_semaphore;
}
@ -180,6 +184,7 @@ namespace etl
count -= timer.delta;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.p_router != ETL_NULLPTR)
{
@ -190,6 +195,7 @@ namespace etl
{
timer.delta = timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
}
has_active = !active_list.empty();
@ -231,10 +237,12 @@ namespace etl
if (timer.is_active())
{
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
timer.delta = immediate_ ? 0U : timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
--process_semaphore;
result = true;
@ -264,6 +272,7 @@ namespace etl
{
++process_semaphore;
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
--process_semaphore;
}
@ -332,6 +341,34 @@ namespace etl
return delta;
}
//*******************************************
/// Set a callback when a timer is inserted on list
//*******************************************
void set_insert_callback(event_callback_type insert_)
{
insert_callback = insert_;
}
//*******************************************
/// Set a callback when a timer is removed from list
//*******************************************
void set_remove_callback(event_callback_type remove_)
{
remove_callback = remove_;
}
//*******************************************
void clear_insert_callback()
{
insert_callback.clear();
}
//*******************************************
void clear_remove_callback()
{
remove_callback.clear();
}
protected:
//*************************************************************************
@ -620,6 +657,9 @@ namespace etl
mutable TSemaphore process_semaphore;
uint_least8_t registered_timers;
event_callback_type insert_callback;
event_callback_type remove_callback;
public:
const uint_least8_t MAX_TIMERS;

View File

@ -54,6 +54,8 @@ namespace etl
typedef etl::delegate<void(void)> callback_type;
typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
public:
//*******************************************
@ -116,6 +118,7 @@ namespace etl
(void)guard; // Silence 'unused variable warnings.
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
}
// Reset in-place.
@ -187,6 +190,7 @@ namespace etl
count -= timer.delta;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.p_router != ETL_NULLPTR)
{
@ -198,6 +202,7 @@ namespace etl
// Reinsert the timer.
timer.delta = timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
}
has_active = !active_list.empty();
@ -240,10 +245,12 @@ namespace etl
if (timer.is_active())
{
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
timer.delta = immediate_ ? 0 : timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
result = true;
}
@ -274,6 +281,7 @@ namespace etl
(void)guard; // Silence 'unused variable warnings.
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
result = true;
@ -340,6 +348,34 @@ namespace etl
return delta;
}
//*******************************************
/// Set a callback when a timer is inserted on list
//*******************************************
void set_insert_callback(event_callback_type insert_)
{
insert_callback = insert_;
}
//*******************************************
/// Set a callback when a timer is removed from list
//*******************************************
void set_remove_callback(event_callback_type remove_)
{
remove_callback = remove_;
}
//*******************************************
void clear_insert_callback()
{
insert_callback.clear();
}
//*******************************************
void clear_remove_callback()
{
remove_callback.clear();
}
protected:
//*************************************************************************
@ -626,6 +662,9 @@ namespace etl
bool enabled;
uint_least8_t number_of_registered_timers;
event_callback_type insert_callback;
event_callback_type remove_callback;
public:
const uint_least8_t Max_Timers;

View File

@ -56,6 +56,8 @@ namespace etl
typedef etl::delegate<void(void)> lock_type;
typedef etl::delegate<void(void)> unlock_type;
typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
public:
//*******************************************
@ -113,6 +115,7 @@ namespace etl
{
lock();
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
unlock();
}
@ -184,6 +187,7 @@ namespace etl
count -= timer.delta;
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.p_router != ETL_NULLPTR)
{
@ -194,6 +198,7 @@ namespace etl
{
timer.delta = timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
}
has_active = !active_list.empty();
@ -237,10 +242,12 @@ namespace etl
if (timer.is_active())
{
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
}
timer.delta = immediate_ ? 0 : timer.period;
active_list.insert(timer.id);
insert_callback.call_if(timer.id);
unlock();
result = true;
@ -270,6 +277,7 @@ namespace etl
{
lock();
active_list.remove(timer.id, false);
remove_callback.call_if(timer.id);
unlock();
}
@ -348,6 +356,34 @@ namespace etl
return delta;
}
//*******************************************
/// Set a callback when a timer is inserted on list
//*******************************************
void set_insert_callback(event_callback_type insert_)
{
insert_callback = insert_;
}
//*******************************************
/// Set a callback when a timer is removed from list
//*******************************************
void set_remove_callback(event_callback_type remove_)
{
remove_callback = remove_;
}
//*******************************************
void clear_insert_callback()
{
insert_callback.clear();
}
//*******************************************
void clear_remove_callback()
{
remove_callback.clear();
}
protected:
//*************************************************************************
@ -638,6 +674,8 @@ namespace etl
lock_type lock; ///< The callback that locks.
unlock_type unlock; ///< The callback that unlocks.
event_callback_type insert_callback;
event_callback_type remove_callback;
public:
const uint_least8_t Max_Timers;

View File

@ -81,10 +81,42 @@ namespace
etl::callback_timer<3>* p_controller;
};
using event_callback_type = etl::icallback_timer::event_callback_type;
Object object;
etl::function_imv<Object, object, &Object::callback> member_callback;
etl::function_imv<Object, object, &Object::callback2> member_callback2;
class TimerInsertRemoveTest
{
public:
uint32_t inserted;
uint32_t removed;
TimerInsertRemoveTest() : inserted(0), removed(0)
{
}
void insert_handler(etl::timer::id::type id_)
{
(void)id_;
inserted++;
}
void remove_handler(etl::timer::id::type id_)
{
(void)id_;
removed++;
}
void clear(void)
{
inserted = 0;
removed = 0;
}
};
TimerInsertRemoveTest timerInsertRemoveTest;
//***************************************************************************
// Free function callback via etl::function
//***************************************************************************
@ -762,36 +794,55 @@ namespace
//*************************************************************************
TEST(callback_timer_is_active)
{
timerInsertRemoveTest.clear();
etl::callback_timer<4> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(free_callback2, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.enable(true);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_TRUE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.tick(11);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(1, timerInsertRemoveTest.removed);
timer_controller.tick(23 - 11);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(37 - 23);
CHECK_FALSE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************

View File

@ -86,10 +86,42 @@ namespace
using callback_type = etl::icallback_timer_atomic<std::atomic_uint32_t>::callback_type;
using event_callback_type = etl::icallback_timer_atomic<std::atomic_uint32_t>::event_callback_type;
Object object;
callback_type member_callback1 = callback_type::create<Object, object, &Object::callback1>();
callback_type member_callback2 = callback_type::create<Object, object, &Object::callback2>();
class TimerInsertRemoveTest
{
public:
uint32_t inserted;
uint32_t removed;
TimerInsertRemoveTest() : inserted(0), removed(0)
{
}
void insert_handler(etl::timer::id::type id_)
{
(void)id_;
inserted++;
}
void remove_handler(etl::timer::id::type id_)
{
(void)id_;
removed++;
}
void clear(void)
{
inserted = 0;
removed = 0;
}
};
TimerInsertRemoveTest timerInsertRemoveTest;
//***************************************************************************
// Free function callback via etl::function
//***************************************************************************
@ -767,36 +799,55 @@ namespace
//*************************************************************************
TEST(callback_timer_is_active)
{
timerInsertRemoveTest.clear();
etl::callback_timer_atomic<3, std::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(member_callback1, 37, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback1, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.enable(true);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_TRUE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.tick(11);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(1, timerInsertRemoveTest.removed);
timer_controller.tick(23 - 11);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(37 - 23);
CHECK_FALSE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************

View File

@ -147,6 +147,8 @@ namespace
using lock_type = etl::icallback_timer_locked::lock_type;
using unlock_type = etl::icallback_timer_locked::unlock_type;
using event_callback_type = etl::icallback_timer_locked::event_callback_type;
Object object;
callback_type member_callback = callback_type::create<Object, object, &Object::callback>();
callback_type member_callback2 = callback_type::create<Object, object, &Object::callback2>();
@ -154,6 +156,36 @@ namespace
callback_type member_callback_inc2 = callback_type::create<Object, object, &Object::callback_inc2>();
callback_type member_callback_inc3 = callback_type::create<Object, object, &Object::callback_inc3>();
class TimerInsertRemoveTest
{
public:
uint32_t inserted;
uint32_t removed;
TimerInsertRemoveTest() : inserted(0), removed(0)
{
}
void insert_handler(etl::timer::id::type id_)
{
(void)id_;
inserted++;
}
void remove_handler(etl::timer::id::type id_)
{
(void)id_;
removed++;
}
void clear(void)
{
inserted = 0;
removed = 0;
}
};
TimerInsertRemoveTest timerInsertRemoveTest;
//***************************************************************************
// Free function callback via etl::function
//***************************************************************************
@ -980,6 +1012,7 @@ namespace
//*************************************************************************
TEST(callback_timer_is_active)
{
timerInsertRemoveTest.clear();
locks.clear();
try_lock_type try_lock = try_lock_type::create<Locks, locks, &Locks::try_lock>();
lock_type lock = lock_type::create<Locks, locks, &Locks::lock>();
@ -991,33 +1024,51 @@ namespace
etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.enable(true);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_TRUE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.tick(11);
timer_controller.handle_deferred();
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(1, timerInsertRemoveTest.removed);
timer_controller.tick(23 - 11);
timer_controller.handle_deferred();
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(37 - 23);
timer_controller.handle_deferred();
CHECK_FALSE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************
@ -1034,6 +1085,9 @@ namespace
etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
@ -1042,7 +1096,7 @@ namespace
timer_controller.tick(11);
timer_controller.handle_deferred();
CHECK_EQUAL(12, timer_controller.time_to_next());
CHECK_EQUAL(23 - 11, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
timer_controller.tick(23);

View File

@ -99,10 +99,42 @@ namespace
using callback_type = etl::icallback_timer_interrupt<ScopedGuard>::callback_type;
using event_callback_type = etl::icallback_timer_interrupt<ScopedGuard>::event_callback_type;
Object object;
callback_type member_callback = callback_type::create<Object, object, &Object::callback>();
callback_type member_callback2 = callback_type::create<Object, object, &Object::callback2>();
class TimerInsertRemoveTest
{
public:
uint32_t inserted;
uint32_t removed;
TimerInsertRemoveTest() : inserted(0), removed(0)
{
}
void insert_handler(etl::timer::id::type id_)
{
(void)id_;
inserted++;
}
void remove_handler(etl::timer::id::type id_)
{
(void)id_;
removed++;
}
void clear(void)
{
inserted = 0;
removed = 0;
}
};
TimerInsertRemoveTest timerInsertRemoveTest;
//***************************************************************************
// Free function callback via etl::function
//***************************************************************************
@ -775,36 +807,55 @@ namespace
//*************************************************************************
TEST(callback_timer_is_active)
{
timerInsertRemoveTest.clear();
etl::callback_timer_interrupt<3, ScopedGuard> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(member_callback, 37, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.enable(true);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_TRUE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.tick(11);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(1, timerInsertRemoveTest.removed);
timer_controller.tick(23 - 11);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(37 - 23);
CHECK_FALSE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************

View File

@ -121,10 +121,42 @@ namespace
using lock_type = etl::icallback_timer_locked::lock_type;
using unlock_type = etl::icallback_timer_locked::unlock_type;
using event_callback_type = etl::icallback_timer_locked::event_callback_type;
Object object;
callback_type member_callback = callback_type::create<Object, object, &Object::callback>();
callback_type member_callback2 = callback_type::create<Object, object, &Object::callback2>();
class TimerInsertRemoveTest
{
public:
uint32_t inserted;
uint32_t removed;
TimerInsertRemoveTest() : inserted(0), removed(0)
{
}
void insert_handler(etl::timer::id::type id_)
{
(void)id_;
inserted++;
}
void remove_handler(etl::timer::id::type id_)
{
(void)id_;
removed++;
}
void clear(void)
{
inserted = 0;
removed = 0;
}
};
TimerInsertRemoveTest timerInsertRemoveTest;
//***************************************************************************
// Free function callback via etl::function
//***************************************************************************
@ -874,6 +906,7 @@ namespace
//*************************************************************************
TEST(callback_timer_is_active)
{
timerInsertRemoveTest.clear();
locks.clear();
try_lock_type try_lock = try_lock_type::create<Locks, locks, &Locks::try_lock>();
lock_type lock = lock_type::create<Locks, locks, &Locks::lock>();
@ -885,30 +918,48 @@ namespace
etl::timer::id::type id2 = timer_controller.register_timer(free_function_callback, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(free_function_callback2, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.enable(true);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_TRUE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.tick(11);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_TRUE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(1, timerInsertRemoveTest.removed);
timer_controller.tick(23 - 11);
CHECK_TRUE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(37 - 23);
CHECK_FALSE(timer_controller.is_active(id1));
CHECK_FALSE(timer_controller.is_active(id2));
CHECK_FALSE(timer_controller.is_active(id3));
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************

View File

@ -134,6 +134,38 @@ namespace
Router1 router1;
Bus1 bus1;
using event_callback_type = etl::imessage_timer::event_callback_type;
class TimerInsertRemoveTest
{
public:
uint32_t inserted;
uint32_t removed;
TimerInsertRemoveTest() : inserted(0), removed(0)
{
}
void insert_handler(etl::timer::id::type id_)
{
(void)id_;
inserted++;
}
void remove_handler(etl::timer::id::type id_)
{
(void)id_;
removed++;
}
void clear(void)
{
inserted = 0;
removed = 0;
}
};
TimerInsertRemoveTest timerInsertRemoveTest;
SUITE(test_message_timer)
{
//*************************************************************************
@ -646,35 +678,57 @@ namespace
//*************************************************************************
TEST(message_timer_time_to_next_with_has_active_timer)
{
timerInsertRemoveTest.clear();
etl::message_timer<3> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(message3, router1, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
router1.clear();
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.enable(true);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.tick(11);
CHECK_EQUAL(12, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(1, timerInsertRemoveTest.removed);
timer_controller.tick(23);
CHECK_EQUAL(3, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(2);
CHECK_EQUAL(1, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(1);
CHECK_EQUAL(static_cast<etl::timer::interval::type>(etl::timer::interval::No_Active_Interval), timer_controller.time_to_next());
CHECK_FALSE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************

View File

@ -134,6 +134,38 @@ namespace
Router1 router1;
Bus1 bus1;
using event_callback_type = etl::imessage_timer_atomic<std::atomic_uint32_t>::event_callback_type;
class TimerInsertRemoveTest
{
public:
uint32_t inserted;
uint32_t removed;
TimerInsertRemoveTest() : inserted(0), removed(0)
{
}
void insert_handler(etl::timer::id::type id_)
{
(void)id_;
inserted++;
}
void remove_handler(etl::timer::id::type id_)
{
(void)id_;
removed++;
}
void clear(void)
{
inserted = 0;
removed = 0;
}
};
TimerInsertRemoveTest timerInsertRemoveTest;
SUITE(test_message_timer)
{
//*************************************************************************
@ -646,35 +678,57 @@ namespace
//*************************************************************************
TEST(message_timer_time_to_next_with_has_active_timer)
{
timerInsertRemoveTest.clear();
etl::message_timer_atomic<3, std::atomic_uint32_t> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(message3, router1, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
router1.clear();
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.enable(true);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.tick(11);
CHECK_EQUAL(12, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(1, timerInsertRemoveTest.removed);
timer_controller.tick(23);
CHECK_EQUAL(3, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(2);
CHECK_EQUAL(1, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(1);
CHECK_EQUAL(static_cast<etl::timer::interval::type>(etl::timer::interval::No_Active_Interval), timer_controller.time_to_next());
CHECK_FALSE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************

View File

@ -157,6 +157,38 @@ namespace
Router1 router1;
Bus1 bus1;
using event_callback_type = etl::imessage_timer_interrupt<ScopedGuard>::event_callback_type;
class TimerInsertRemoveTest
{
public:
uint32_t inserted;
uint32_t removed;
TimerInsertRemoveTest() : inserted(0), removed(0)
{
}
void insert_handler(etl::timer::id::type id_)
{
(void)id_;
inserted++;
}
void remove_handler(etl::timer::id::type id_)
{
(void)id_;
removed++;
}
void clear(void)
{
inserted = 0;
removed = 0;
}
};
TimerInsertRemoveTest timerInsertRemoveTest;
SUITE(test_message_timer_interrupt)
{
//*************************************************************************
@ -693,35 +725,57 @@ namespace
//*************************************************************************
TEST(message_timer_time_to_next_with_has_active_timer)
{
timerInsertRemoveTest.clear();
etl::message_timer_interrupt<3, ScopedGuard> timer_controller;
etl::timer::id::type id1 = timer_controller.register_timer(message1, router1, 37, etl::timer::mode::Single_Shot);
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(message3, router1, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
router1.clear();
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.enable(true);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.tick(11);
CHECK_EQUAL(12, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(1, timerInsertRemoveTest.removed);
timer_controller.tick(23);
CHECK_EQUAL(3, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(2);
CHECK_EQUAL(1, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(1);
CHECK_EQUAL(static_cast<etl::timer::interval::type>(etl::timer::interval::No_Active_Interval), timer_controller.time_to_next());
CHECK_FALSE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************

View File

@ -168,6 +168,38 @@ namespace
Router1 router1;
Bus1 bus1;
using event_callback_type = etl::imessage_timer_locked::event_callback_type;
class TimerInsertRemoveTest
{
public:
uint32_t inserted;
uint32_t removed;
TimerInsertRemoveTest() : inserted(0), removed(0)
{
}
void insert_handler(etl::timer::id::type id_)
{
(void)id_;
inserted++;
}
void remove_handler(etl::timer::id::type id_)
{
(void)id_;
removed++;
}
void clear(void)
{
inserted = 0;
removed = 0;
}
};
TimerInsertRemoveTest timerInsertRemoveTest;
using try_lock_type = etl::imessage_timer_locked::try_lock_type;
using lock_type = etl::imessage_timer_locked::lock_type;
using unlock_type = etl::imessage_timer_locked::unlock_type;
@ -773,6 +805,7 @@ namespace
//*************************************************************************
TEST(message_timer_time_to_next_with_has_active_timer)
{
timerInsertRemoveTest.clear();
locks.clear();
try_lock_type try_lock = try_lock_type::create<Locks, locks, &Locks::try_lock>();
lock_type lock = lock_type::create<Locks, locks, &Locks::lock>();
@ -784,29 +817,50 @@ namespace
etl::timer::id::type id2 = timer_controller.register_timer(message2, router1, 23, etl::timer::mode::Single_Shot);
etl::timer::id::type id3 = timer_controller.register_timer(message3, router1, 11, etl::timer::mode::Single_Shot);
timer_controller.set_insert_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::insert_handler>());
timer_controller.set_remove_callback(event_callback_type::create<TimerInsertRemoveTest, timerInsertRemoveTest, &TimerInsertRemoveTest::remove_handler>());
router1.clear();
timer_controller.start(id1);
timer_controller.start(id3);
timer_controller.start(id2);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.enable(true);
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(0, timerInsertRemoveTest.removed);
timer_controller.tick(11);
CHECK_EQUAL(12, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(1, timerInsertRemoveTest.removed);
timer_controller.tick(23);
CHECK_EQUAL(3, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(2);
CHECK_EQUAL(1, timer_controller.time_to_next());
CHECK_TRUE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(2, timerInsertRemoveTest.removed);
timer_controller.tick(1);
CHECK_EQUAL(static_cast<etl::timer::interval::type>(etl::timer::interval::No_Active_Interval), timer_controller.time_to_next());
CHECK_FALSE(timer_controller.has_active_timer());
CHECK_EQUAL(3, timerInsertRemoveTest.inserted);
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************

View File

@ -11376,11 +11376,13 @@
<None Include="..\..\.github\workflows\clang-c++14.yml" />
<None Include="..\..\.github\workflows\clang-c++17.yml" />
<None Include="..\..\.github\workflows\clang-c++20.yml" />
<None Include="..\..\.github\workflows\clang-c++23.yml" />
<None Include="..\..\.github\workflows\clang-syntax-checks.yml" />
<None Include="..\..\.github\workflows\gcc-c++11.yml" />
<None Include="..\..\.github\workflows\gcc-c++14.yml" />
<None Include="..\..\.github\workflows\gcc-c++17.yml" />
<None Include="..\..\.github\workflows\gcc-c++20.yml" />
<None Include="..\..\.github\workflows\gcc-c++23.yml" />
<None Include="..\..\.github\workflows\msvc.yml" />
<None Include="..\..\.github\workflows\gcc-syntax-checks.yml" />
<None Include="..\..\.github\workflows\platformio-update.yml" />

View File

@ -3886,6 +3886,12 @@
<None Include="..\..\..\etl-arduino\.github\workflows\platformio-update.yml">
<Filter>ETL\Arduino</Filter>
</None>
<None Include="..\..\.github\workflows\clang-c++23.yml">
<Filter>Resource Files\CI\Github</Filter>
</None>
<None Include="..\..\.github\workflows\gcc-c++23.yml">
<Filter>Resource Files\CI\Github</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\support\Release notes.txt">