mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Initial code. Committed for reference
This commit is contained in:
parent
60ba92928e
commit
fe1bc0b029
694
include/etl/intrusive_callback_timer.h
Normal file
694
include/etl/intrusive_callback_timer.h
Normal file
@ -0,0 +1,694 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2017 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_CALLBACK_TIMER_INCLUDED
|
||||
#define ETL_CALLBACK_TIMER_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "algorithm.h"
|
||||
#include "atomic.h"
|
||||
#include "delegate.h"
|
||||
#include "error_handler.h"
|
||||
#include "function.h"
|
||||
#include "nullptr.h"
|
||||
#include "placement_new.h"
|
||||
#include "static_assert.h"
|
||||
#include "timer_data.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// Interface for callback timer
|
||||
//***************************************************************************
|
||||
class iintrusive_callback_timer
|
||||
{
|
||||
public:
|
||||
|
||||
typedef etl::delegate<void(void)> callback_type;
|
||||
|
||||
typedef etl::delegate<void(etl::timer_data::id::type, uint32_t delta)> event_callback_type;
|
||||
|
||||
//*******************************************
|
||||
/// Register a timer.
|
||||
//*******************************************
|
||||
etl::timer::id::type register_timer(void (*p_callback_)(), uint32_t period_, bool repeating_)
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Register a timer.
|
||||
//*******************************************
|
||||
etl::timer::id::type register_timer(etl::ifunction<void>& callback_, uint32_t period_, bool repeating_)
|
||||
{
|
||||
etl::timer::id::type id = etl::timer::id::NO_TIMER;
|
||||
|
||||
bool is_space = (registered_timers < MAX_TIMERS);
|
||||
|
||||
if (is_space)
|
||||
{
|
||||
// Search for the free space.
|
||||
for (uint_least8_t i = 0U; i < MAX_TIMERS; ++i)
|
||||
{
|
||||
timer_data& timer = timer_array[i];
|
||||
|
||||
if (timer.id == etl::timer::id::NO_TIMER)
|
||||
{
|
||||
// Create in-place.
|
||||
new (&timer) timer_data(i, callback_, period_, repeating_);
|
||||
++registered_timers;
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Register a timer.
|
||||
//*******************************************
|
||||
#if ETL_USING_CPP11
|
||||
etl::timer::id::type register_timer(callback_type& callback_, uint32_t period_, bool repeating_)
|
||||
{
|
||||
etl::timer::id::type id = etl::timer::id::NO_TIMER;
|
||||
|
||||
bool is_space = (registered_timers < MAX_TIMERS);
|
||||
|
||||
if (is_space)
|
||||
{
|
||||
// Search for the free space.
|
||||
for (uint_least8_t i = 0U; i < MAX_TIMERS; ++i)
|
||||
{
|
||||
timer_data& timer = timer_array[i];
|
||||
|
||||
if (timer.id == etl::timer::id::NO_TIMER)
|
||||
{
|
||||
// Create in-place.
|
||||
new (&timer) timer_data(i, callback_, period_, repeating_);
|
||||
++registered_timers;
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
#endif
|
||||
|
||||
//*******************************************
|
||||
/// Unregister a timer.
|
||||
//*******************************************
|
||||
bool unregister_timer(etl::timer::id::type id_)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (id_ != etl::timer::id::NO_TIMER)
|
||||
{
|
||||
timer_data& timer = timer_array[id_];
|
||||
|
||||
if (timer.id != etl::timer::id::NO_TIMER)
|
||||
{
|
||||
if (timer.is_active())
|
||||
{
|
||||
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) timer_data();
|
||||
--registered_timers;
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Enable/disable the timer.
|
||||
//*******************************************
|
||||
void enable(bool state_)
|
||||
{
|
||||
enabled = state_;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Get the enable/disable state.
|
||||
//*******************************************
|
||||
bool is_running() const
|
||||
{
|
||||
return enabled;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Clears the timer of data.
|
||||
//*******************************************
|
||||
void clear()
|
||||
{
|
||||
ETL_DISABLE_TIMER_UPDATES;
|
||||
active_list.clear();
|
||||
ETL_ENABLE_TIMER_UPDATES;
|
||||
|
||||
for (int i = 0; i < MAX_TIMERS; ++i)
|
||||
{
|
||||
::new (&timer_array[i]) timer_data();
|
||||
}
|
||||
|
||||
registered_timers = 0;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
// Called by the timer service to indicate the
|
||||
// amount of time that has elapsed since the last successful call to 'tick'.
|
||||
// Returns true if the tick was processed,
|
||||
// false if not.
|
||||
//*******************************************
|
||||
bool tick(uint32_t count)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
if (ETL_TIMER_UPDATES_ENABLED)
|
||||
{
|
||||
// We have something to do?
|
||||
bool has_active = !active_list.empty();
|
||||
|
||||
if (has_active)
|
||||
{
|
||||
while (has_active && (count >= active_list.front().delta))
|
||||
{
|
||||
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 == timer_data::C_CALLBACK)
|
||||
{
|
||||
// Call the C callback.
|
||||
reinterpret_cast<void (*)()>(timer.p_callback)();
|
||||
}
|
||||
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 == timer_data::DELEGATE)
|
||||
{
|
||||
// Call the delegate callback.
|
||||
(*reinterpret_cast<callback_type*>(timer.p_callback))();
|
||||
}
|
||||
}
|
||||
|
||||
has_active = !active_list.empty();
|
||||
}
|
||||
|
||||
if (has_active)
|
||||
{
|
||||
// Subtract any remainder from the next due timeout.
|
||||
active_list.front().delta -= count;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Starts a timer.
|
||||
//*******************************************
|
||||
bool start(etl::timer::id::type id_, bool immediate_ = false)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// Valid timer id?
|
||||
if (id_ != etl::timer::id::NO_TIMER)
|
||||
{
|
||||
timer_data& timer = timer_array[id_];
|
||||
|
||||
// Registered timer?
|
||||
if (timer.id != etl::timer::id::NO_TIMER)
|
||||
{
|
||||
// Has a valid period.
|
||||
if (timer.period != etl::timer::state::Inactive)
|
||||
{
|
||||
ETL_DISABLE_TIMER_UPDATES;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Stops a timer.
|
||||
//*******************************************
|
||||
bool stop(etl::timer::id::type id_)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// Valid timer id?
|
||||
if (id_ != etl::timer::id::NO_TIMER)
|
||||
{
|
||||
timer_data& timer = timer_array[id_];
|
||||
|
||||
// Registered timer?
|
||||
if (timer.id != etl::timer::id::NO_TIMER)
|
||||
{
|
||||
if (timer.is_active())
|
||||
{
|
||||
ETL_DISABLE_TIMER_UPDATES;
|
||||
active_list.remove(timer.id, false);
|
||||
remove_callback.call_if(timer.id);
|
||||
ETL_ENABLE_TIMER_UPDATES;
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Sets a timer's period.
|
||||
//*******************************************
|
||||
bool set_period(etl::timer::id::type id_, uint32_t period_)
|
||||
{
|
||||
if (stop(id_))
|
||||
{
|
||||
timer_array[id_].period = period_;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Sets a timer's mode.
|
||||
//*******************************************
|
||||
bool set_mode(etl::timer::id::type id_, bool repeating_)
|
||||
{
|
||||
if (stop(id_))
|
||||
{
|
||||
timer_array[id_].repeating = repeating_;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Returns true if an attempt was ever made to insert a timer into the
|
||||
/// active list when it was already there. Such an insert is rejected, as
|
||||
/// it would create a circular reference in the list.
|
||||
//*******************************************
|
||||
bool duplicate_insert_detected() const
|
||||
{
|
||||
return active_list.duplicate_insert_detected();
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Check if there is an active timer.
|
||||
//*******************************************
|
||||
bool has_active_timer() const
|
||||
{
|
||||
return !active_list.empty();
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Get the time to the next timer event.
|
||||
/// Returns etl::timer::interval::No_Active_Interval if there is no active
|
||||
/// timer.
|
||||
//*******************************************
|
||||
uint32_t time_to_next() const
|
||||
{
|
||||
uint32_t delta = static_cast<uint32_t>(etl::timer::interval::No_Active_Interval);
|
||||
|
||||
if (has_active_timer())
|
||||
{
|
||||
delta = active_list.front().delta;
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Checks if a timer is currently active.
|
||||
/// Returns <b>true</b> if the timer is active, otherwise <b>false</b>.
|
||||
//*******************************************
|
||||
bool is_active(etl::timer::id::type id_) const
|
||||
{
|
||||
//// Valid timer id?
|
||||
// if (is_valid_timer_id(id_))
|
||||
//{
|
||||
// if (has_active_timer())
|
||||
// {
|
||||
// const timer_data& timer = timer_array[id_];
|
||||
|
||||
// // Registered timer?
|
||||
// if (timer.id != etl::timer::id::NO_TIMER)
|
||||
// {
|
||||
// return timer.is_active();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
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:
|
||||
|
||||
//*******************************************
|
||||
/// Constructor.
|
||||
//*******************************************
|
||||
icallback_timer(timer_data* const timer_array_, const uint_least8_t Max_Timers_)
|
||||
: timer_array(timer_array_)
|
||||
, active_list(timer_array_)
|
||||
, enabled(false)
|
||||
,
|
||||
#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK)
|
||||
process_semaphore(0)
|
||||
,
|
||||
#endif
|
||||
registered_timers(0)
|
||||
, MAX_TIMERS(Max_Timers_)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*******************************************
|
||||
/// Check that the timer id is valid.
|
||||
//*******************************************
|
||||
bool is_valid_timer_id(etl::timer::id::type id_) const
|
||||
{
|
||||
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)
|
||||
, ptimers(ptimers_)
|
||||
, duplicate_insert(false)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const
|
||||
{
|
||||
return head == etl::timer::id::NO_TIMER;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns true if an attempt was ever made to insert a timer that was
|
||||
/// already in the list.
|
||||
//*******************************
|
||||
bool duplicate_insert_detected() const
|
||||
{
|
||||
return duplicate_insert;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Inserts the timer at the correct delta position
|
||||
//*******************************
|
||||
void insert(etl::timer::id::type id_)
|
||||
{
|
||||
timer_data& timer = ptimers[id_];
|
||||
|
||||
// A timer is in this list exactly when it is the head or has a previous
|
||||
// link, as remove() clears both links. Inserting one that is already
|
||||
// here would link it to itself and create a circular reference, so
|
||||
// record the attempt and abandon the insert to keep the list intact.
|
||||
if ((head == id_) || (timer.previous != etl::timer::id::NO_TIMER))
|
||||
{
|
||||
duplicate_insert = true;
|
||||
return;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
etl::timer::id::type next(etl::timer::id::type last)
|
||||
{
|
||||
return ptimers[last].next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
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;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
etl::timer::id::type head;
|
||||
etl::timer::id::type tail;
|
||||
|
||||
timer_data* const ptimers;
|
||||
|
||||
// Set if an attempt was ever made to insert a timer that was already
|
||||
// in the list.
|
||||
bool duplicate_insert;
|
||||
};
|
||||
|
||||
// The array of timer data structures.
|
||||
timer_data* const timer_array;
|
||||
|
||||
// The list of active timers.
|
||||
timer_list active_list;
|
||||
|
||||
volatile bool enabled;
|
||||
uint_least8_t registered_timers;
|
||||
|
||||
event_callback_type timeout_callback;
|
||||
|
||||
etl::timer_data terminator;
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// The callback timer
|
||||
//***************************************************************************
|
||||
class intrusive_callback_timer : public etl::iintrusive_callback_timer
|
||||
{
|
||||
public:
|
||||
|
||||
private:
|
||||
};
|
||||
} // namespace etl
|
||||
|
||||
#endif
|
||||
588
include/etl/timer_config.h
Normal file
588
include/etl/timer_config.h
Normal file
@ -0,0 +1,588 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2026 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef ETL_TIMER_DATA_INCLUDED
|
||||
#define ETL_TIMER_DATA_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "nullptr.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//*****************************************************************************
|
||||
// Definitions common to intrusive timers.
|
||||
//*****************************************************************************
|
||||
|
||||
namespace etl
|
||||
{
|
||||
//***************************************************************************
|
||||
/// Common definitions for the intrusive timer framework.
|
||||
//***************************************************************************
|
||||
class timer_config
|
||||
{
|
||||
public:
|
||||
|
||||
friend class timer_register_list;
|
||||
friend class timer_active_list;
|
||||
friend class timer_triggered_list;
|
||||
friend class intrusive_callback_timer;
|
||||
|
||||
//*******************************************
|
||||
timer_config() ETL_NOEXCEPT
|
||||
: period(etl::timer::state::Inactive)
|
||||
, delta(etl::timer::state::Inactive)
|
||||
, mode(etl::timer::mode::Repeating)
|
||||
, registered_next(ETL_NULLPTR)
|
||||
, active_next(ETL_NULLPTR)
|
||||
, triggered_next(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
timer_config(uint32_t period_, etl::timer::mode::type repeating_) ETL_NOEXCEPT
|
||||
: period(period_)
|
||||
, delta(period_)
|
||||
, mode(repeating_)
|
||||
, registered_next(ETL_NULLPTR)
|
||||
, active_next(ETL_NULLPTR)
|
||||
, triggered_next(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
uint32_t get_period() const ETL_NOEXCEPT
|
||||
{
|
||||
return period;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
uint32_t get_delta() const ETL_NOEXCEPT
|
||||
{
|
||||
return delta;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
uint32_t get_mode() const ETL_NOEXCEPT
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
void clear() ETL_NOEXCEPT
|
||||
{
|
||||
period = etl::timer::state::Inactive;
|
||||
delta = etl::timer::state::Inactive;
|
||||
mode = etl::timer::mode::Repeating;
|
||||
registered_next = ETL_NULLPTR;
|
||||
active_next = ETL_NULLPTR;
|
||||
triggered_next = ETL_NULLPTR;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t period; ///< The period of the timer.
|
||||
uint32_t delta; ///< The time remaining until the timer expires.
|
||||
timer_config* registered_next; ///< The next timer in the registered timer list. nullptr if the timer is not registered.
|
||||
timer_config* active_next; ///< The next timer in the active timer list. nullptr if the timer is not active.
|
||||
timer_config* triggered_next; ///< The next timer in the triggered timer list. nullptr if the timer is not triggered.
|
||||
etl::timer::mode::type mode; ///< Whether the timer is repeating or single-shot.
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// A timer data structure that includes a callback delegate.
|
||||
//***************************************************************************
|
||||
template <typename TCallback>
|
||||
struct callback_timer_config : public timer_config
|
||||
{
|
||||
callback_timer_config(etl::timer::id::type id_, TCallback callback_) ETL_NOEXCEPT
|
||||
: timer_config()
|
||||
, callback(callback_)
|
||||
{
|
||||
}
|
||||
|
||||
TCallback callback; ///< The callback delegate for the timer.
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// The list of timers that are registered.
|
||||
//*************************************************************************
|
||||
class timer_register_list
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************
|
||||
timer_register_list() ETL_NOEXCEPT
|
||||
: head(ETL_NULLPTR)
|
||||
, tail(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const
|
||||
{
|
||||
return head == ETL_NULLPTR;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Adds the timer in to the list.
|
||||
//*******************************
|
||||
void insert(etl::timer_config* new_timer) ETL_NOEXCEPT
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
head = new_timer;
|
||||
}
|
||||
else if (head == new_timer)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove any existing timer.
|
||||
etl::timer_config* previous = head;
|
||||
|
||||
// Step through the list until we find the timer to remove, or reach the end of the list.
|
||||
while ((previous->registered_next != ETL_NULLPTR) && (previous->registered_next != new_timer))
|
||||
{
|
||||
previous = previous->registered_next;
|
||||
}
|
||||
|
||||
// If we found the timer, remove it from the list.
|
||||
if (previous->registered_next == new_timer)
|
||||
{
|
||||
}
|
||||
|
||||
tail->registered_next = new_timer;
|
||||
}
|
||||
|
||||
tail = new_timer;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Remove the timer from the list.
|
||||
// Returns the next timer in the list after the removed timer, or nullptr if the removed timer was the last in the list.
|
||||
//*******************************
|
||||
etl::timer_config* remove(etl::timer_config* timer) ETL_NOEXCEPT
|
||||
{
|
||||
if (timer == head)
|
||||
{
|
||||
head = timer->registered_next;
|
||||
|
||||
if (head == ETL_NULLPTR)
|
||||
{
|
||||
tail = ETL_NULLPTR;
|
||||
}
|
||||
|
||||
timer->registered_next = ETL_NULLPTR;
|
||||
|
||||
return head;
|
||||
}
|
||||
else
|
||||
{
|
||||
etl::timer_config* previous = head;
|
||||
|
||||
// Step through the list until we find the timer to remove, or reach the end of the list.
|
||||
while ((previous->registered_next != ETL_NULLPTR) && (previous->registered_next != timer))
|
||||
{
|
||||
previous = previous->registered_next;
|
||||
}
|
||||
|
||||
// If we found the timer, remove it from the list.
|
||||
if (previous->registered_next == timer)
|
||||
{
|
||||
previous->registered_next = timer->registered_next;
|
||||
|
||||
if (timer == tail)
|
||||
{
|
||||
tail = previous;
|
||||
}
|
||||
|
||||
timer->registered_next = ETL_NULLPTR;
|
||||
|
||||
return previous->registered_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Timer not found in the list.
|
||||
return ETL_NULLPTR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the first timer in the list.
|
||||
/// If the list is empty, returns nullptr.
|
||||
//*******************************
|
||||
etl::timer_config* first() const ETL_NOEXCEPT
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the next timer in the list after the given timer.
|
||||
/// May be nullptr if the given timer is the last in the list.
|
||||
/// If the given timer is nullptr, returns nullptr.
|
||||
//*******************************
|
||||
etl::timer_config* next(etl::timer_config* timer) const ETL_NOEXCEPT
|
||||
{
|
||||
if (timer != ETL_NULLPTR)
|
||||
{
|
||||
return timer->registered_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ETL_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Clear the list of entries.
|
||||
//*******************************
|
||||
void clear()
|
||||
{
|
||||
etl::timer_config* timer = head;
|
||||
|
||||
while (timer != ETL_NULLPTR)
|
||||
{
|
||||
timer = pop_front();
|
||||
}
|
||||
|
||||
head = ETL_NULLPTR;
|
||||
tail = ETL_NULLPTR;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*******************************
|
||||
// Removes the timer at the front of the list.
|
||||
// Returns the new head of the list, which may be nullptr if the list is now empty.
|
||||
//*******************************
|
||||
etl::timer_config* pop_front() ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer_config* timer = head;
|
||||
head = timer->registered_next;
|
||||
timer->registered_next = ETL_NULLPTR;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
etl::timer_config* head;
|
||||
etl::timer_config* tail;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// The list of timers that are active.
|
||||
//*************************************************************************
|
||||
class timer_active_list
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************
|
||||
timer_active_list() ETL_NOEXCEPT
|
||||
: head(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const ETL_NOEXCEPT
|
||||
{
|
||||
return head == ETL_NULLPTR;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Inserts the timer at the correct delta position
|
||||
//*******************************
|
||||
void insert(etl::timer_config* new_timer) ETL_NOEXCEPT
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
// No entries yet.
|
||||
head = new_timer;
|
||||
new_timer->active_next = ETL_NULLPTR;
|
||||
}
|
||||
else if (new_timer->delta < head->delta)
|
||||
{
|
||||
// Goes before the head.
|
||||
head->delta -= new_timer->delta;
|
||||
new_timer->active_next = head;
|
||||
head = new_timer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We already have entries, and new_timer doesn't go before head.
|
||||
timer_config* previous_timer = head;
|
||||
timer_config* timer = head->active_next;
|
||||
|
||||
// Adjust the new_timer delta to take account of the head timer's delta.
|
||||
new_timer->delta -= previous_timer->delta;
|
||||
|
||||
bool inserted = false;
|
||||
|
||||
while (!inserted && (timer != ETL_NULLPTR))
|
||||
{
|
||||
// Find the correct place to insert.
|
||||
// The list is sorted by delta, so we need to find the first timer with a delta greater than the new timer's delta.
|
||||
if (new_timer->delta < timer->delta)
|
||||
{
|
||||
// Insert after the previous timer.
|
||||
previous_timer->active_next = new_timer;
|
||||
new_timer->active_next = timer;
|
||||
|
||||
// Adjust the next delta for the new timer's delta.
|
||||
timer->delta -= new_timer->delta;
|
||||
|
||||
inserted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adjust the new_timer delta to take account of the last timer's delta.
|
||||
new_timer->delta -= timer->delta;
|
||||
}
|
||||
|
||||
// Move to the next timer in the list.
|
||||
previous_timer = timer;
|
||||
timer = timer->active_next;
|
||||
}
|
||||
|
||||
if (!inserted)
|
||||
{
|
||||
// Reached the end so attach to the tail.
|
||||
previous_timer->active_next = new_timer;
|
||||
new_timer->active_next = ETL_NULLPTR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Removes the selected timer from the list.
|
||||
// No action is taken if the timer is not found.
|
||||
// returns the next timer in the list after the removed timer, or nullptr if the removed timer was the last in the list.
|
||||
//*******************************
|
||||
etl::timer_config* remove(etl::timer_config* timer) ETL_NOEXCEPT
|
||||
{
|
||||
// Find the timer in the list.
|
||||
etl::timer_config* current = head;
|
||||
etl::timer_config* last = ETL_NULLPTR;
|
||||
|
||||
while (current != timer && current != ETL_NULLPTR)
|
||||
{
|
||||
last = current;
|
||||
current = current->active_next;
|
||||
}
|
||||
|
||||
// Not found?
|
||||
if (current == ETL_NULLPTR)
|
||||
{
|
||||
return ETL_NULLPTR;
|
||||
}
|
||||
|
||||
etl::timer_config* next = current->active_next;
|
||||
|
||||
// Adjust the next delta.
|
||||
if (next != ETL_NULLPTR)
|
||||
{
|
||||
next->delta += current->delta;
|
||||
}
|
||||
|
||||
// Remove it from the list.
|
||||
if (last == ETL_NULLPTR)
|
||||
{
|
||||
head = next;
|
||||
}
|
||||
else
|
||||
{
|
||||
last->active_next = next;
|
||||
}
|
||||
|
||||
// Clear the next pointer of the removed timer.
|
||||
current->active_next = ETL_NULLPTR;
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the first timer in the list.
|
||||
/// If the list is empty, returns nullptr.
|
||||
//*******************************
|
||||
etl::timer_config* first() const ETL_NOEXCEPT
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the next timer in the list after the given timer.
|
||||
/// If the given timer is nullptr, returns nullptr.
|
||||
//*******************************
|
||||
etl::timer_config* next(etl::timer_config* timer) const ETL_NOEXCEPT
|
||||
{
|
||||
if (timer != ETL_NULLPTR)
|
||||
{
|
||||
return timer->active_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ETL_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Clear the list of entries.
|
||||
//*******************************
|
||||
void clear()
|
||||
{
|
||||
etl::timer_config* timer = head;
|
||||
|
||||
while (timer != ETL_NULLPTR)
|
||||
{
|
||||
timer = pop_front();
|
||||
}
|
||||
|
||||
head = ETL_NULLPTR;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*******************************
|
||||
// Removes the timer at the front of the list.
|
||||
// Returns the new head of the list, which may be nullptr if the list is now empty.
|
||||
//*******************************
|
||||
etl::timer_config* pop_front() ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer_config* timer = head;
|
||||
head = timer->active_next;
|
||||
timer->active_next = ETL_NULLPTR;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
etl::timer_config* head;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// The list of timers that are registered.
|
||||
//*************************************************************************
|
||||
class timer_triggered_list
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************
|
||||
timer_triggered_list() ETL_NOEXCEPT
|
||||
: head(ETL_NULLPTR)
|
||||
, tail(ETL_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const
|
||||
{
|
||||
return head == ETL_NULLPTR;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Adds the timer in to the list.
|
||||
//*******************************
|
||||
void insert(etl::timer_config* new_timer) ETL_NOEXCEPT
|
||||
{
|
||||
new_timer->triggered_next = ETL_NULLPTR;
|
||||
|
||||
if (empty())
|
||||
{
|
||||
head = new_timer;
|
||||
}
|
||||
else
|
||||
{
|
||||
tail->triggered_next = new_timer;
|
||||
}
|
||||
|
||||
tail = new_timer;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the first timer in the list.
|
||||
/// If the list is empty, returns nullptr.
|
||||
//*******************************
|
||||
etl::timer_config* first() const ETL_NOEXCEPT
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the next timer in the list after the given timer.
|
||||
/// May be nullptr if the given timer is the last in the list.
|
||||
/// If the given timer is nullptr, returns nullptr.
|
||||
//*******************************
|
||||
etl::timer_config* next(etl::timer_config* timer) const ETL_NOEXCEPT
|
||||
{
|
||||
if (timer != ETL_NULLPTR)
|
||||
{
|
||||
return timer->triggered_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ETL_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Clear the list of entries.
|
||||
//*******************************
|
||||
void clear()
|
||||
{
|
||||
etl::timer_config* timer = head;
|
||||
|
||||
while (timer != ETL_NULLPTR)
|
||||
{
|
||||
timer = pop_front();
|
||||
}
|
||||
|
||||
head = ETL_NULLPTR;
|
||||
tail = ETL_NULLPTR;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*******************************
|
||||
// Removes the timer at the front of the list.
|
||||
// Returns the new head of the list, which may be nullptr if the list is now empty.
|
||||
//*******************************
|
||||
etl::timer_config* pop_front() ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer_config* timer = head;
|
||||
head = timer->triggered_next;
|
||||
timer->triggered_next = ETL_NULLPTR;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
etl::timer_config* head;
|
||||
etl::timer_config* tail;
|
||||
};
|
||||
} // namespace etl
|
||||
|
||||
#endif
|
||||
319
test/test_timer_data.cpp
Normal file
319
test/test_timer_data.cpp
Normal file
@ -0,0 +1,319 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2026 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "unit_test_framework.h"
|
||||
|
||||
#include "etl/timer_config.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
SUITE(test_timer_config)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_register_list)
|
||||
{
|
||||
etl::timer_config timer1;
|
||||
etl::timer_config timer2;
|
||||
etl::timer_config timer3;
|
||||
etl::timer_config timer4;
|
||||
etl::timer_config timer5;
|
||||
|
||||
etl::timer_register_list register_list;
|
||||
|
||||
CHECK_TRUE(register_list.empty());
|
||||
CHECK_TRUE(register_list.first() == ETL_NULLPTR);
|
||||
|
||||
// Add the timers to the list.
|
||||
register_list.insert(&timer1);
|
||||
register_list.insert(&timer2);
|
||||
register_list.insert(&timer3);
|
||||
register_list.insert(&timer4);
|
||||
register_list.insert(&timer5);
|
||||
|
||||
CHECK_FALSE(register_list.empty());
|
||||
CHECK_TRUE(register_list.first() == &timer1);
|
||||
|
||||
etl::timer_config* timer = register_list.first();
|
||||
|
||||
// The timers should be in the order they were added.
|
||||
CHECK_EQUAL(&timer1, timer);
|
||||
timer = register_list.next(timer);
|
||||
CHECK_EQUAL(&timer2, timer);
|
||||
timer = register_list.next(timer);
|
||||
CHECK_EQUAL(&timer3, timer);
|
||||
timer = register_list.next(timer);
|
||||
CHECK_EQUAL(&timer4, timer);
|
||||
timer = register_list.next(timer);
|
||||
CHECK_EQUAL(&timer5, timer);
|
||||
timer = register_list.next(timer);
|
||||
CHECK_EQUAL(ETL_NULLPTR, timer);
|
||||
|
||||
// Remove timer3 from the list.
|
||||
register_list.remove(&timer3);
|
||||
|
||||
// Search the list to ensure the other timers are still present.
|
||||
bool timer1_found = false;
|
||||
bool timer2_found = false;
|
||||
bool timer3_found = false;
|
||||
bool timer4_found = false;
|
||||
bool timer5_found = false;
|
||||
|
||||
timer = register_list.first();
|
||||
|
||||
while (timer != ETL_NULLPTR)
|
||||
{
|
||||
if (timer == &timer1)
|
||||
{
|
||||
timer1_found = true;
|
||||
}
|
||||
else if (timer == &timer2)
|
||||
{
|
||||
timer2_found = true;
|
||||
}
|
||||
else if (timer == &timer3)
|
||||
{
|
||||
timer3_found = true;
|
||||
}
|
||||
else if (timer == &timer4)
|
||||
{
|
||||
timer4_found = true;
|
||||
}
|
||||
else if (timer == &timer5)
|
||||
{
|
||||
timer5_found = true;
|
||||
}
|
||||
|
||||
timer = register_list.next(timer);
|
||||
}
|
||||
|
||||
CHECK_TRUE(timer1_found);
|
||||
CHECK_TRUE(timer2_found);
|
||||
CHECK_FALSE(timer3_found);
|
||||
CHECK_TRUE(timer4_found);
|
||||
CHECK_TRUE(timer5_found);
|
||||
|
||||
// Clear the list.
|
||||
register_list.clear();
|
||||
|
||||
CHECK_TRUE(register_list.empty());
|
||||
CHECK_TRUE(register_list.first() == ETL_NULLPTR);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_active_list)
|
||||
{
|
||||
etl::timer_config timer1(100, etl::timer::mode::Repeating);
|
||||
etl::timer_config timer2(65, etl::timer::mode::Repeating);
|
||||
etl::timer_config timer3(85, etl::timer::mode::Repeating);
|
||||
etl::timer_config timer4(130, etl::timer::mode::Repeating);
|
||||
etl::timer_config timer5(85, etl::timer::mode::Repeating);
|
||||
etl::timer_config timer6(85, etl::timer::mode::Repeating);
|
||||
|
||||
etl::timer_active_list active_list;
|
||||
|
||||
CHECK_TRUE(active_list.empty());
|
||||
CHECK_TRUE(active_list.first() == ETL_NULLPTR);
|
||||
|
||||
active_list.insert(&timer1);
|
||||
active_list.insert(&timer2);
|
||||
active_list.insert(&timer3);
|
||||
active_list.insert(&timer4);
|
||||
active_list.insert(&timer5);
|
||||
|
||||
CHECK_FALSE(active_list.empty());
|
||||
CHECK_TRUE(active_list.first() == &timer2);
|
||||
|
||||
etl::timer_config* timer = active_list.first();
|
||||
|
||||
// The timers should be in the order of their deltas.
|
||||
CHECK_EQUAL(&timer2, timer);
|
||||
timer = active_list.next(timer);
|
||||
CHECK_EQUAL(&timer3, timer);
|
||||
timer = active_list.next(timer);
|
||||
CHECK_EQUAL(&timer5, timer);
|
||||
timer = active_list.next(timer);
|
||||
CHECK_EQUAL(&timer1, timer);
|
||||
timer = active_list.next(timer);
|
||||
CHECK_EQUAL(&timer4, timer);
|
||||
timer = active_list.next(timer);
|
||||
CHECK_EQUAL(ETL_NULLPTR, timer);
|
||||
|
||||
CHECK_EQUAL(timer2.get_period(), timer2.get_delta());
|
||||
CHECK_EQUAL(timer3.get_period() - timer2.get_period(), timer3.get_delta());
|
||||
CHECK_EQUAL(timer1.get_period() - timer3.get_period(), timer1.get_delta());
|
||||
CHECK_EQUAL(timer4.get_period() - timer1.get_period(), timer4.get_delta());
|
||||
CHECK_EQUAL(timer5.get_period() - timer3.get_period(), timer5.get_delta());
|
||||
|
||||
// Remove timer3 from the list.
|
||||
active_list.remove(&timer3);
|
||||
|
||||
// Search the list to ensure the other timers are still present.
|
||||
bool timer1_found = false;
|
||||
bool timer2_found = false;
|
||||
bool timer3_found = false;
|
||||
bool timer4_found = false;
|
||||
bool timer5_found = false;
|
||||
|
||||
timer = active_list.first();
|
||||
|
||||
while (timer != ETL_NULLPTR)
|
||||
{
|
||||
if (timer == &timer1)
|
||||
{
|
||||
timer1_found = true;
|
||||
}
|
||||
else if (timer == &timer2)
|
||||
{
|
||||
timer2_found = true;
|
||||
}
|
||||
else if (timer == &timer3)
|
||||
{
|
||||
timer3_found = true;
|
||||
}
|
||||
else if (timer == &timer4)
|
||||
{
|
||||
timer4_found = true;
|
||||
}
|
||||
else if (timer == &timer5)
|
||||
{
|
||||
timer5_found = true;
|
||||
}
|
||||
|
||||
timer = active_list.next(timer);
|
||||
}
|
||||
|
||||
CHECK_TRUE(timer1_found);
|
||||
CHECK_TRUE(timer2_found);
|
||||
CHECK_FALSE(timer3_found);
|
||||
CHECK_TRUE(timer4_found);
|
||||
CHECK_TRUE(timer5_found);
|
||||
|
||||
// Check the deltas are still correct.
|
||||
CHECK_EQUAL(timer2.get_period(), timer2.get_delta());
|
||||
CHECK_EQUAL(timer1.get_period() - timer3.get_period(), timer1.get_delta());
|
||||
CHECK_EQUAL(timer4.get_period() - timer1.get_period(), timer4.get_delta());
|
||||
CHECK_EQUAL(timer5.get_period() - timer2.get_period(), timer5.get_delta());
|
||||
|
||||
// Remove a timer that is not in the list.
|
||||
active_list.remove(&timer6);
|
||||
|
||||
// Search the list to ensure the other timers are still present.
|
||||
timer1_found = false;
|
||||
timer2_found = false;
|
||||
timer3_found = false;
|
||||
timer4_found = false;
|
||||
timer5_found = false;
|
||||
|
||||
timer = active_list.first();
|
||||
|
||||
while (timer != ETL_NULLPTR)
|
||||
{
|
||||
if (timer == &timer1)
|
||||
{
|
||||
timer1_found = true;
|
||||
}
|
||||
else if (timer == &timer2)
|
||||
{
|
||||
timer2_found = true;
|
||||
}
|
||||
else if (timer == &timer3)
|
||||
{
|
||||
timer3_found = true;
|
||||
}
|
||||
else if (timer == &timer4)
|
||||
{
|
||||
timer4_found = true;
|
||||
}
|
||||
else if (timer == &timer5)
|
||||
{
|
||||
timer5_found = true;
|
||||
}
|
||||
|
||||
timer = active_list.next(timer);
|
||||
}
|
||||
|
||||
// Check the deltas are still correct.
|
||||
CHECK_EQUAL(timer2.get_period(), timer2.get_delta());
|
||||
CHECK_EQUAL(timer1.get_period() - timer3.get_period(), timer1.get_delta());
|
||||
CHECK_EQUAL(timer4.get_period() - timer1.get_period(), timer4.get_delta());
|
||||
CHECK_EQUAL(timer5.get_period() - timer2.get_period(), timer5.get_delta());
|
||||
|
||||
// Clear the list.
|
||||
active_list.clear();
|
||||
|
||||
CHECK_TRUE(active_list.empty());
|
||||
CHECK_TRUE(active_list.first() == ETL_NULLPTR);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_triggered_list)
|
||||
{
|
||||
etl::timer_config timer1;
|
||||
etl::timer_config timer2;
|
||||
etl::timer_config timer3;
|
||||
etl::timer_config timer4;
|
||||
etl::timer_config timer5;
|
||||
|
||||
etl::timer_triggered_list triggered_list;
|
||||
|
||||
CHECK_TRUE(triggered_list.empty());
|
||||
CHECK_TRUE(triggered_list.first() == ETL_NULLPTR);
|
||||
|
||||
// Add the timers to the list.
|
||||
triggered_list.insert(&timer1);
|
||||
triggered_list.insert(&timer2);
|
||||
triggered_list.insert(&timer3);
|
||||
triggered_list.insert(&timer4);
|
||||
triggered_list.insert(&timer5);
|
||||
|
||||
CHECK_FALSE(triggered_list.empty());
|
||||
CHECK_TRUE(triggered_list.first() == &timer1);
|
||||
|
||||
// The timers should be in the order they were added.
|
||||
etl::timer_config* timer = triggered_list.first();
|
||||
|
||||
CHECK_EQUAL(&timer1, timer);
|
||||
timer = triggered_list.next(timer);
|
||||
CHECK_EQUAL(&timer2, timer);
|
||||
timer = triggered_list.next(timer);
|
||||
CHECK_EQUAL(&timer3, timer);
|
||||
timer = triggered_list.next(timer);
|
||||
CHECK_EQUAL(&timer4, timer);
|
||||
timer = triggered_list.next(timer);
|
||||
CHECK_EQUAL(&timer5, timer);
|
||||
timer = triggered_list.next(timer);
|
||||
CHECK_EQUAL(ETL_NULLPTR, timer);
|
||||
|
||||
// Clear the list.
|
||||
triggered_list.clear();
|
||||
|
||||
CHECK_TRUE(triggered_list.empty());
|
||||
CHECK_TRUE(triggered_list.first() == ETL_NULLPTR);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
@ -3559,6 +3559,7 @@
|
||||
<ClInclude Include="..\..\include\etl\generators\variant_pool_cpp03_generator.h" />
|
||||
<ClInclude Include="..\..\include\etl\index_of_type.h" />
|
||||
<ClInclude Include="..\..\include\etl\inplace_function.h" />
|
||||
<ClInclude Include="..\..\include\etl\timer_config.h" />
|
||||
<ClInclude Include="..\..\include\etl\invoke.h" />
|
||||
<ClInclude Include="..\..\include\etl\lcm.h" />
|
||||
<ClInclude Include="..\..\include\etl\math.h" />
|
||||
@ -11449,6 +11450,7 @@
|
||||
<ClCompile Include="..\test_task_scheduler.cpp" />
|
||||
<ClCompile Include="..\test_threshold.cpp" />
|
||||
<ClCompile Include="..\test_chrono_time_point.cpp" />
|
||||
<ClCompile Include="..\test_timer_data.cpp" />
|
||||
<ClCompile Include="..\test_to_arithmetic.cpp" />
|
||||
<ClCompile Include="..\test_to_arithmetic_u16.cpp" />
|
||||
<ClCompile Include="..\test_to_arithmetic_u32.cpp" />
|
||||
|
||||
@ -226,6 +226,9 @@
|
||||
<Filter Include="Documentation">
|
||||
<UniqueIdentifier>{5b809d95-b37c-4011-af5e-b5ea6dcb354e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Tests\Timer support">
|
||||
<UniqueIdentifier>{c3b8f843-f046-4bf2-ab0a-34e9da0dcfbe}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\etl\enum_type.h">
|
||||
@ -1566,6 +1569,9 @@
|
||||
<ClInclude Include="..\..\include\etl\format.h">
|
||||
<Filter>UnitTest++\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\timer_config.h">
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\test_string_char.cpp">
|
||||
@ -3836,6 +3842,9 @@
|
||||
<ClCompile Include="..\test_vector_member_function_pointer_external_buffer.cpp">
|
||||
<Filter>Tests\Containers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_timer_data.cpp">
|
||||
<Filter>Tests\Timer support</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\library.properties">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user