mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Modified the timer config and node classes
This commit is contained in:
parent
fe1bc0b029
commit
cf07fc69b5
518
include/etl/private/timer_lists.h
Normal file
518
include/etl/private/timer_lists.h
Normal file
@ -0,0 +1,518 @@
|
||||
/******************************************************************************
|
||||
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_LISTS_INCLUDED
|
||||
#define ETL_TIMER_LISTS_INCLUDED
|
||||
|
||||
#include "../platform.h"
|
||||
#include "../nullptr.h"
|
||||
#include "../timer.h"
|
||||
#include "../timer_node.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//*****************************************************************************
|
||||
// Definitions common to intrusive timers.
|
||||
//*****************************************************************************
|
||||
|
||||
namespace etl
|
||||
{
|
||||
namespace private_timer
|
||||
{
|
||||
//*************************************************************************
|
||||
/// The list of timers that are registered.
|
||||
/// The list does not do any checking of parameters as it is assumed that the timer service has already done this.
|
||||
//*************************************************************************
|
||||
class timer_register_list
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************
|
||||
timer_register_list() ETL_NOEXCEPT
|
||||
: head(end())
|
||||
, tail(end())
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const
|
||||
{
|
||||
return head == end();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Adds the timer in to the list.
|
||||
//*******************************
|
||||
void insert(etl::timer_node* new_timer) ETL_NOEXCEPT
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
head = new_timer;
|
||||
}
|
||||
else
|
||||
{
|
||||
tail->registered_next = new_timer;
|
||||
}
|
||||
|
||||
tail = new_timer;
|
||||
new_timer->registered_next = end();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// 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_node* remove(etl::timer_node* timer) ETL_NOEXCEPT
|
||||
{
|
||||
if (timer == head)
|
||||
{
|
||||
head = timer->registered_next;
|
||||
|
||||
if (head == end())
|
||||
{
|
||||
tail = end();
|
||||
}
|
||||
|
||||
timer->registered_next = ETL_NULLPTR;
|
||||
|
||||
return head;
|
||||
}
|
||||
else
|
||||
{
|
||||
etl::timer_node* previous = head;
|
||||
|
||||
// Step through the list until we find the timer to remove, or reach the end of the list.
|
||||
while ((previous->registered_next != end()) && (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 = end();
|
||||
|
||||
return previous->registered_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Timer not found in the list.
|
||||
return end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the first timer in the list.
|
||||
/// If the list is empty, returns end().
|
||||
//*******************************
|
||||
etl::timer_node* first() const ETL_NOEXCEPT
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the next timer in the list after the given timer.
|
||||
/// May be end() if the given timer is the last in the list.
|
||||
/// If the given timer is nullptr, returns end().
|
||||
//*******************************
|
||||
etl::timer_node* next(etl::timer_node* timer) const ETL_NOEXCEPT
|
||||
{
|
||||
if (timer != end())
|
||||
{
|
||||
return timer->registered_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the end of the list.
|
||||
/// Always returns &etl::timer_node::sentinal().
|
||||
//*******************************
|
||||
etl::timer_node* const end() const ETL_NOEXCEPT
|
||||
{
|
||||
return etl::timer_node::sentinal();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Clear the list of entries.
|
||||
//*******************************
|
||||
void clear()
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
|
||||
while (timer != end())
|
||||
{
|
||||
timer = pop_front();
|
||||
}
|
||||
|
||||
head = end();
|
||||
tail = end();
|
||||
}
|
||||
|
||||
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_node* pop_front() ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
head = timer->registered_next;
|
||||
timer->registered_next = timer->unlinked();
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
etl::timer_node* head;
|
||||
etl::timer_node* tail;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// The list of timers that are active.
|
||||
/// The list does not do any checking of parameters as it is assumed that the timer service has already done this.
|
||||
//*************************************************************************
|
||||
class timer_active_list
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************
|
||||
timer_active_list() ETL_NOEXCEPT
|
||||
: head(end())
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const ETL_NOEXCEPT
|
||||
{
|
||||
return head == end();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Inserts the timer at the correct delta position
|
||||
//*******************************
|
||||
void insert(etl::timer_node* new_timer) ETL_NOEXCEPT
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
// No entries yet.
|
||||
head = new_timer;
|
||||
new_timer->active_next = end();
|
||||
}
|
||||
else if (new_timer->config.delta < head->config.delta)
|
||||
{
|
||||
// Goes before the head.
|
||||
head->config.delta -= new_timer->config.delta;
|
||||
new_timer->active_next = head;
|
||||
head = new_timer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We already have entries, and new_timer doesn't go before head.
|
||||
timer_node* previous_timer = head;
|
||||
timer_node* timer = head->active_next;
|
||||
|
||||
// Adjust the new_timer delta to take account of the head timer's delta.
|
||||
new_timer->config.delta -= previous_timer->config.delta;
|
||||
|
||||
bool inserted = false;
|
||||
|
||||
while (!inserted && (timer != end()))
|
||||
{
|
||||
// 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->config.delta < timer->config.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->config.delta -= new_timer->config.delta;
|
||||
|
||||
inserted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adjust the new_timer delta to take account of the last timer's delta.
|
||||
new_timer->config.delta -= timer->config.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 = end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// 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 end() if the removed timer was the last in the list.
|
||||
/// The list does not do any checking of parameters as it is assumed that the timer service has already done this.
|
||||
//*******************************
|
||||
etl::timer_node* remove(etl::timer_node* timer) ETL_NOEXCEPT
|
||||
{
|
||||
// Find the timer in the list.
|
||||
etl::timer_node* current = head;
|
||||
etl::timer_node* last = end();
|
||||
|
||||
while (current != timer && current != end())
|
||||
{
|
||||
last = current;
|
||||
current = current->active_next;
|
||||
}
|
||||
|
||||
// Not found?
|
||||
if (current == end())
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
etl::timer_node* next = current->active_next;
|
||||
|
||||
// Adjust the next delta.
|
||||
if (next != end())
|
||||
{
|
||||
next->config.delta += current->config.delta;
|
||||
}
|
||||
|
||||
// Remove it from the list.
|
||||
if (last == end())
|
||||
{
|
||||
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 end().
|
||||
//*******************************
|
||||
etl::timer_node* first() const ETL_NOEXCEPT
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the next timer in the list after the given timer.
|
||||
/// May be end() if the given timer is the last in the list.
|
||||
/// If the given timer is nullptr, returns end().
|
||||
//*******************************
|
||||
etl::timer_node* next(etl::timer_node* timer) const ETL_NOEXCEPT
|
||||
{
|
||||
if (timer != end())
|
||||
{
|
||||
return timer->active_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the end of the list.
|
||||
/// Always returns &etl::timer_node::sentinal().
|
||||
//*******************************
|
||||
etl::timer_node* const end() const ETL_NOEXCEPT
|
||||
{
|
||||
return etl::timer_node::sentinal();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Clear the list of entries.
|
||||
//*******************************
|
||||
void clear()
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
|
||||
while (timer != end())
|
||||
{
|
||||
timer = pop_front();
|
||||
}
|
||||
|
||||
head = end();
|
||||
}
|
||||
|
||||
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_node* pop_front() ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
head = timer->active_next;
|
||||
timer->active_next = timer->unlinked();
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
etl::timer_node* head;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// The list of timers that are registered.
|
||||
//*************************************************************************
|
||||
class timer_triggered_list
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************
|
||||
timer_triggered_list() ETL_NOEXCEPT
|
||||
: head(end())
|
||||
, tail(end())
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const
|
||||
{
|
||||
return head == end();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Adds the timer in to the list.
|
||||
//*******************************
|
||||
void insert(etl::timer_node* new_timer) ETL_NOEXCEPT
|
||||
{
|
||||
new_timer->triggered_next = end();
|
||||
|
||||
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_node* first() const ETL_NOEXCEPT
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the next timer in the list after the given timer.
|
||||
/// May be end() if the given timer is the last in the list.
|
||||
/// If the given timer is nullptr, returns end().
|
||||
//*******************************
|
||||
etl::timer_node* next(etl::timer_node* timer) const ETL_NOEXCEPT
|
||||
{
|
||||
if (timer != end())
|
||||
{
|
||||
return timer->triggered_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the end of the list.
|
||||
/// Always returns &etl::timer_node::sentinal().
|
||||
//*******************************
|
||||
etl::timer_node* const end() const ETL_NOEXCEPT
|
||||
{
|
||||
return etl::timer_node::sentinal();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Clear the list of entries.
|
||||
//*******************************
|
||||
void clear()
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
|
||||
while (timer != end())
|
||||
{
|
||||
timer = pop_front();
|
||||
}
|
||||
|
||||
head = end();
|
||||
tail = end();
|
||||
}
|
||||
|
||||
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_node* pop_front() ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
head = timer->triggered_next;
|
||||
timer->triggered_next = timer->unlinked();
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
etl::timer_node* head;
|
||||
etl::timer_node* tail;
|
||||
};
|
||||
} // namespace private_timer
|
||||
} // namespace etl
|
||||
|
||||
#endif
|
||||
@ -1,588 +0,0 @@
|
||||
/******************************************************************************
|
||||
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
|
||||
515
include/etl/timer_lists.h
Normal file
515
include/etl/timer_lists.h
Normal file
@ -0,0 +1,515 @@
|
||||
/******************************************************************************
|
||||
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_LISTS_INCLUDED
|
||||
#define ETL_TIMER_LISTS_INCLUDED
|
||||
|
||||
#include "../platform.h"
|
||||
#include "../nullptr.h"
|
||||
#include "../timer_node.h"
|
||||
|
||||
//*****************************************************************************
|
||||
// Definitions common to intrusive timers.
|
||||
//*****************************************************************************
|
||||
|
||||
namespace etl
|
||||
{
|
||||
namespace private_timer
|
||||
{
|
||||
//*************************************************************************
|
||||
/// The list of timers that are registered.
|
||||
/// The list does not do any checking of parameters as it is assumed that the timer service has already done this.
|
||||
//*************************************************************************
|
||||
class timer_register_list
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************
|
||||
timer_register_list() ETL_NOEXCEPT
|
||||
: head(end())
|
||||
, tail(end())
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const
|
||||
{
|
||||
return head == end();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Adds the timer in to the list.
|
||||
//*******************************
|
||||
void insert(etl::timer_node* new_timer) ETL_NOEXCEPT
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
head = new_timer;
|
||||
}
|
||||
else
|
||||
{
|
||||
tail->registered_next = new_timer;
|
||||
}
|
||||
|
||||
tail = new_timer;
|
||||
new_timer->registered_next = end();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// 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_node* remove(etl::timer_node* timer) ETL_NOEXCEPT
|
||||
{
|
||||
if (timer == head)
|
||||
{
|
||||
head = timer->registered_next;
|
||||
|
||||
if (head == end())
|
||||
{
|
||||
tail = end();
|
||||
}
|
||||
|
||||
timer->registered_next = ETL_NULLPTR;
|
||||
|
||||
return head;
|
||||
}
|
||||
else
|
||||
{
|
||||
etl::timer_node* previous = head;
|
||||
|
||||
// Step through the list until we find the timer to remove, or reach the end of the list.
|
||||
while ((previous->registered_next != end()) && (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 = end();
|
||||
|
||||
return previous->registered_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Timer not found in the list.
|
||||
return end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the first timer in the list.
|
||||
/// If the list is empty, returns end().
|
||||
//*******************************
|
||||
etl::timer_node* first() const ETL_NOEXCEPT
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the next timer in the list after the given timer.
|
||||
/// May be end() if the given timer is the last in the list.
|
||||
/// If the given timer is nullptr, returns end().
|
||||
//*******************************
|
||||
etl::timer_node* next(etl::timer_node* timer) const ETL_NOEXCEPT
|
||||
{
|
||||
if (timer != end())
|
||||
{
|
||||
return timer->registered_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the end of the list.
|
||||
/// Always returns &etl::timer_node::sentinal().
|
||||
//*******************************
|
||||
etl::timer_node* const end() const ETL_NOEXCEPT
|
||||
{
|
||||
return etl::timer_node::sentinal();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Clear the list of entries.
|
||||
//*******************************
|
||||
void clear()
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
|
||||
while (timer != end())
|
||||
{
|
||||
timer = pop_front();
|
||||
}
|
||||
|
||||
head = end();
|
||||
tail = end();
|
||||
}
|
||||
|
||||
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_node* pop_front() ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
head = timer->registered_next;
|
||||
timer->registered_next = timer->unlinked();
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
etl::timer_node* head;
|
||||
etl::timer_node* tail;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// The list of timers that are active.
|
||||
/// The list does not do any checking of parameters as it is assumed that the timer service has already done this.
|
||||
//*************************************************************************
|
||||
class timer_active_list
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************
|
||||
timer_active_list() ETL_NOEXCEPT
|
||||
: head(end())
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const ETL_NOEXCEPT
|
||||
{
|
||||
return head == end();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Inserts the timer at the correct delta position
|
||||
//*******************************
|
||||
void insert(etl::timer_node* new_timer) ETL_NOEXCEPT
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
// No entries yet.
|
||||
head = new_timer;
|
||||
new_timer->active_next = end();
|
||||
}
|
||||
else if (new_timer->config.delta < head->config.delta)
|
||||
{
|
||||
// Goes before the head.
|
||||
head->config.delta -= new_timer->config.delta;
|
||||
new_timer->active_next = head;
|
||||
head = new_timer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We already have entries, and new_timer doesn't go before head.
|
||||
timer_node* previous_timer = head;
|
||||
timer_node* timer = head->active_next;
|
||||
|
||||
// Adjust the new_timer delta to take account of the head timer's delta.
|
||||
new_timer->config.delta -= previous_timer->config.delta;
|
||||
|
||||
bool inserted = false;
|
||||
|
||||
while (!inserted && (timer != end()))
|
||||
{
|
||||
// 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->config.delta < timer->config.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->config.delta -= new_timer->config.delta;
|
||||
|
||||
inserted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adjust the new_timer delta to take account of the last timer's delta.
|
||||
new_timer->config.delta -= timer->config.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 = end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// 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 end() if the removed timer was the last in the list.
|
||||
/// The list does not do any checking of parameters as it is assumed that the timer service has already done this.
|
||||
//*******************************
|
||||
etl::timer_node* remove(etl::timer_node* timer) ETL_NOEXCEPT
|
||||
{
|
||||
// Find the timer in the list.
|
||||
etl::timer_node* current = head;
|
||||
etl::timer_node* last = end();
|
||||
|
||||
while (current != timer && current != end())
|
||||
{
|
||||
last = current;
|
||||
current = current->active_next;
|
||||
}
|
||||
|
||||
// Not found?
|
||||
if (current == end())
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
etl::timer_node* next = current->active_next;
|
||||
|
||||
// Adjust the next delta.
|
||||
if (next != end())
|
||||
{
|
||||
next->config.delta += current->config.delta;
|
||||
}
|
||||
|
||||
// Remove it from the list.
|
||||
if (last == end())
|
||||
{
|
||||
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 end().
|
||||
//*******************************
|
||||
etl::timer_node* first() const ETL_NOEXCEPT
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the next timer in the list after the given timer.
|
||||
/// May be end() if the given timer is the last in the list.
|
||||
/// If the given timer is nullptr, returns end().
|
||||
//*******************************
|
||||
etl::timer_node* next(etl::timer_node* timer) const ETL_NOEXCEPT
|
||||
{
|
||||
if (timer != end())
|
||||
{
|
||||
return timer->active_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the end of the list.
|
||||
/// Always returns &etl::timer_node::sentinal().
|
||||
//*******************************
|
||||
etl::timer_node* const end() const ETL_NOEXCEPT
|
||||
{
|
||||
return etl::timer_node::sentinal();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Clear the list of entries.
|
||||
//*******************************
|
||||
void clear()
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
|
||||
while (timer != end())
|
||||
{
|
||||
timer = pop_front();
|
||||
}
|
||||
|
||||
head = end();
|
||||
}
|
||||
|
||||
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_node* pop_front() ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
head = timer->active_next;
|
||||
timer->active_next = timer->unlinked();
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
etl::timer_node* head;
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// The list of timers that are registered.
|
||||
//*************************************************************************
|
||||
class timer_triggered_list
|
||||
{
|
||||
public:
|
||||
|
||||
//*******************************
|
||||
timer_triggered_list() ETL_NOEXCEPT
|
||||
: head(end())
|
||||
, tail(end())
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************
|
||||
bool empty() const
|
||||
{
|
||||
return head == end();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
// Adds the timer in to the list.
|
||||
//*******************************
|
||||
void insert(etl::timer_node* new_timer) ETL_NOEXCEPT
|
||||
{
|
||||
new_timer->triggered_next = end();
|
||||
|
||||
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_node* first() const ETL_NOEXCEPT
|
||||
{
|
||||
return head;
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the next timer in the list after the given timer.
|
||||
/// May be end() if the given timer is the last in the list.
|
||||
/// If the given timer is nullptr, returns end().
|
||||
//*******************************
|
||||
etl::timer_node* next(etl::timer_node* timer) const ETL_NOEXCEPT
|
||||
{
|
||||
if (timer != end())
|
||||
{
|
||||
return timer->triggered_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Returns the end of the list.
|
||||
/// Always returns &etl::timer_node::sentinal().
|
||||
//*******************************
|
||||
etl::timer_node* const end() const ETL_NOEXCEPT
|
||||
{
|
||||
return etl::timer_node::sentinal();
|
||||
}
|
||||
|
||||
//*******************************
|
||||
/// Clear the list of entries.
|
||||
//*******************************
|
||||
void clear()
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
|
||||
while (timer != end())
|
||||
{
|
||||
timer = pop_front();
|
||||
}
|
||||
|
||||
head = end();
|
||||
tail = end();
|
||||
}
|
||||
|
||||
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_node* pop_front() ETL_NOEXCEPT
|
||||
{
|
||||
etl::timer_node* timer = head;
|
||||
head = timer->triggered_next;
|
||||
timer->triggered_next = timer->unlinked();
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
etl::timer_node* head;
|
||||
etl::timer_node* tail;
|
||||
};
|
||||
} // namespace private_timer
|
||||
} // namespace etl
|
||||
|
||||
#endif
|
||||
221
include/etl/timer_node.h
Normal file
221
include/etl/timer_node.h
Normal file
@ -0,0 +1,221 @@
|
||||
/******************************************************************************
|
||||
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_NODE_INCLUDED
|
||||
#define ETL_TIMER_NODE_INCLUDED
|
||||
|
||||
#include "platform.h"
|
||||
#include "nullptr.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//*****************************************************************************
|
||||
// Definitions common to intrusive timers.
|
||||
//*****************************************************************************
|
||||
|
||||
namespace etl
|
||||
{
|
||||
namespace private_timer
|
||||
{
|
||||
class timer_register_list;
|
||||
class timer_active_list;
|
||||
class timer_triggered_list;
|
||||
|
||||
class intrusive_callback_timer;
|
||||
} // namespace private_timer
|
||||
|
||||
//***************************************************************************
|
||||
/// A timer configuration data structure.
|
||||
//***************************************************************************
|
||||
class timer_config
|
||||
{
|
||||
public:
|
||||
|
||||
friend class private_timer::timer_register_list;
|
||||
friend class private_timer::timer_active_list;
|
||||
friend class private_timer::timer_triggered_list;
|
||||
|
||||
friend class intrusive_callback_timer;
|
||||
|
||||
//*******************************************
|
||||
/// Constructor.
|
||||
//*******************************************
|
||||
ETL_CONSTEXPR timer_config(uint32_t period_, etl::timer::mode::type repeating_) ETL_NOEXCEPT
|
||||
: period(period_)
|
||||
, delta(period_)
|
||||
, mode(repeating_)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Returns the period of the timer.
|
||||
//*******************************************
|
||||
ETL_CONSTEXPR uint32_t get_period() const ETL_NOEXCEPT
|
||||
{
|
||||
return period;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Returns the time remaining until the timer expires.
|
||||
//*******************************************
|
||||
ETL_CONSTEXPR uint32_t get_delta() const ETL_NOEXCEPT
|
||||
{
|
||||
return delta;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Returns the mode of the timer.
|
||||
//*******************************************
|
||||
ETL_CONSTEXPR uint32_t get_mode() const ETL_NOEXCEPT
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Clears the timer configuration.
|
||||
//*******************************************
|
||||
ETL_CONSTEXPR14 void clear() ETL_NOEXCEPT
|
||||
{
|
||||
period = etl::timer::state::Inactive;
|
||||
delta = etl::timer::state::Inactive;
|
||||
mode = etl::timer::mode::Repeating;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
uint32_t period; ///< The period of the timer.
|
||||
uint32_t delta; ///< The time remaining until the timer expires.
|
||||
etl::timer::mode::type mode; ///< Whether the timer is repeating or single-shot.
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
/// A timer data structure that can be linked into the timer lists.
|
||||
/// Contains a timer configuration.
|
||||
//***************************************************************************
|
||||
class timer_node
|
||||
{
|
||||
public:
|
||||
|
||||
friend class private_timer::timer_register_list;
|
||||
friend class private_timer::timer_active_list;
|
||||
friend class private_timer::timer_triggered_list;
|
||||
|
||||
friend class intrusive_callback_timer;
|
||||
|
||||
//*******************************************
|
||||
/// Constructor.
|
||||
//*******************************************
|
||||
timer_node(const timer_config& config_) ETL_NOEXCEPT
|
||||
: registered_next(unlinked())
|
||||
, active_next(unlinked())
|
||||
, triggered_next(unlinked())
|
||||
, config(config_)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Copy constructor.
|
||||
//*******************************************
|
||||
timer_node(const timer_node& node_) ETL_NOEXCEPT
|
||||
: registered_next(unlinked())
|
||||
, active_next(unlinked())
|
||||
, triggered_next(unlinked())
|
||||
, config(node_.config)
|
||||
{
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Returns the configuration of the timer.
|
||||
//*******************************************
|
||||
const timer_config& get_config() const ETL_NOEXCEPT
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
//*******************************************
|
||||
/// Returns a nullptr to indicate that the timer is not linked into any list.
|
||||
//*******************************************
|
||||
static etl::timer_node* unlinked() ETL_NOEXCEPT
|
||||
{
|
||||
return ETL_NULLPTR;
|
||||
}
|
||||
|
||||
//***************************************************************************
|
||||
/// Returns a reference to the sentinel timer node used to mark the end of
|
||||
/// the intrusive timer lists.
|
||||
/// Implemented as a function-local static so that there is only ever one
|
||||
/// instance, regardless of how many translation units include this header.
|
||||
/// This avoids needing C++17 inline variables, so it remains compatible
|
||||
/// with C++03 and C++11.
|
||||
//***************************************************************************
|
||||
static etl::timer_node* sentinal() ETL_NOEXCEPT
|
||||
{
|
||||
static etl::timer_node timer_sentinel(etl::timer_config(0, 0));
|
||||
|
||||
return &timer_sentinel;
|
||||
}
|
||||
|
||||
//*******************************************
|
||||
/// Clear the next pointers.
|
||||
//*******************************************
|
||||
void clear() ETL_NOEXCEPT
|
||||
{
|
||||
registered_next = unlinked();
|
||||
active_next = unlinked();
|
||||
triggered_next = unlinked();
|
||||
}
|
||||
|
||||
timer_node& operator=(const timer_node&) ETL_DELETE;
|
||||
|
||||
timer_node* registered_next; ///< The next timer in the registered timer list. nullptr if the timer is not registered.
|
||||
timer_node* active_next; ///< The next timer in the active timer list. nullptr if the timer is not active.
|
||||
timer_node* triggered_next; ///< The next timer in the triggered timer list. nullptr if the timer is not triggered.
|
||||
|
||||
timer_config config; ///< The configuration of the timer.
|
||||
};
|
||||
|
||||
////***************************************************************************
|
||||
///// A timer data structure that includes a callback delegate.
|
||||
////***************************************************************************
|
||||
// template <typename TCallback>
|
||||
// struct callback_timer_config : public timer_node
|
||||
//{
|
||||
// callback_timer_config(TCallback callback_) ETL_NOEXCEPT
|
||||
// : timer_config()
|
||||
// , callback(callback_)
|
||||
// {
|
||||
// }
|
||||
|
||||
// TCallback callback; ///< The callback delegate for the timer.
|
||||
//};
|
||||
} // namespace etl
|
||||
|
||||
#endif
|
||||
@ -28,25 +28,32 @@ SOFTWARE.
|
||||
|
||||
#include "unit_test_framework.h"
|
||||
|
||||
#include "etl/timer_config.h"
|
||||
#include "etl/timer_node.h"
|
||||
#include "etl/private/timer_lists.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
SUITE(test_timer_config)
|
||||
SUITE(test_timer_lists)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_register_list)
|
||||
TEST(test_timer_register_list)
|
||||
{
|
||||
etl::timer_config timer1;
|
||||
etl::timer_config timer2;
|
||||
etl::timer_config timer3;
|
||||
etl::timer_config timer4;
|
||||
etl::timer_config timer5;
|
||||
constexpr etl::timer_config timer1_config(100, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer2_config(65, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer3_config(85, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer4_config(130, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer5_config(85, etl::timer::mode::Repeating);
|
||||
|
||||
etl::timer_register_list register_list;
|
||||
etl::timer_node timer1{timer1_config};
|
||||
etl::timer_node timer2{timer2_config};
|
||||
etl::timer_node timer3{timer3_config};
|
||||
etl::timer_node timer4{timer4_config};
|
||||
etl::timer_node timer5{timer5_config};
|
||||
|
||||
etl::private_timer::timer_register_list register_list;
|
||||
|
||||
CHECK_TRUE(register_list.empty());
|
||||
CHECK_TRUE(register_list.first() == ETL_NULLPTR);
|
||||
CHECK_TRUE(register_list.first() == register_list.end());
|
||||
|
||||
// Add the timers to the list.
|
||||
register_list.insert(&timer1);
|
||||
@ -58,7 +65,7 @@ namespace
|
||||
CHECK_FALSE(register_list.empty());
|
||||
CHECK_TRUE(register_list.first() == &timer1);
|
||||
|
||||
etl::timer_config* timer = register_list.first();
|
||||
etl::timer_node* timer = register_list.first();
|
||||
|
||||
// The timers should be in the order they were added.
|
||||
CHECK_EQUAL(&timer1, timer);
|
||||
@ -71,7 +78,7 @@ namespace
|
||||
timer = register_list.next(timer);
|
||||
CHECK_EQUAL(&timer5, timer);
|
||||
timer = register_list.next(timer);
|
||||
CHECK_EQUAL(ETL_NULLPTR, timer);
|
||||
CHECK_EQUAL(register_list.end(), timer);
|
||||
|
||||
// Remove timer3 from the list.
|
||||
register_list.remove(&timer3);
|
||||
@ -85,7 +92,7 @@ namespace
|
||||
|
||||
timer = register_list.first();
|
||||
|
||||
while (timer != ETL_NULLPTR)
|
||||
while (timer != register_list.end())
|
||||
{
|
||||
if (timer == &timer1)
|
||||
{
|
||||
@ -121,23 +128,30 @@ namespace
|
||||
register_list.clear();
|
||||
|
||||
CHECK_TRUE(register_list.empty());
|
||||
CHECK_TRUE(register_list.first() == ETL_NULLPTR);
|
||||
CHECK_TRUE(register_list.first() == register_list.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_active_list)
|
||||
TEST(test_timer_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);
|
||||
constexpr etl::timer_config timer1_config(100, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer2_config(65, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer3_config(85, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer4_config(130, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer5_config(85, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer6_config(85, etl::timer::mode::Repeating);
|
||||
|
||||
etl::timer_active_list active_list;
|
||||
etl::timer_node timer1(timer1_config);
|
||||
etl::timer_node timer2(timer2_config);
|
||||
etl::timer_node timer3(timer3_config);
|
||||
etl::timer_node timer4(timer4_config);
|
||||
etl::timer_node timer5(timer5_config);
|
||||
etl::timer_node timer6(timer6_config);
|
||||
|
||||
etl::private_timer::timer_active_list active_list;
|
||||
|
||||
CHECK_TRUE(active_list.empty());
|
||||
CHECK_TRUE(active_list.first() == ETL_NULLPTR);
|
||||
CHECK_TRUE(active_list.first() == active_list.end());
|
||||
|
||||
active_list.insert(&timer1);
|
||||
active_list.insert(&timer2);
|
||||
@ -148,7 +162,7 @@ namespace
|
||||
CHECK_FALSE(active_list.empty());
|
||||
CHECK_TRUE(active_list.first() == &timer2);
|
||||
|
||||
etl::timer_config* timer = active_list.first();
|
||||
etl::timer_node* timer = active_list.first();
|
||||
|
||||
// The timers should be in the order of their deltas.
|
||||
CHECK_EQUAL(&timer2, timer);
|
||||
@ -161,14 +175,13 @@ namespace
|
||||
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());
|
||||
CHECK_EQUAL(active_list.end(), timer);
|
||||
|
||||
CHECK_EQUAL(timer2.get_config().get_period(), timer2.get_config().get_delta());
|
||||
CHECK_EQUAL(timer3.get_config().get_period() - timer2.get_config().get_period(), timer3.get_config().get_delta());
|
||||
CHECK_EQUAL(timer1.get_config().get_period() - timer3.get_config().get_period(), timer1.get_config().get_delta());
|
||||
CHECK_EQUAL(timer4.get_config().get_period() - timer1.get_config().get_period(), timer4.get_config().get_delta());
|
||||
CHECK_EQUAL(timer5.get_config().get_period() - timer3.get_config().get_period(), timer5.get_config().get_delta());
|
||||
// Remove timer3 from the list.
|
||||
active_list.remove(&timer3);
|
||||
|
||||
@ -181,7 +194,7 @@ namespace
|
||||
|
||||
timer = active_list.first();
|
||||
|
||||
while (timer != ETL_NULLPTR)
|
||||
while (timer != active_list.end())
|
||||
{
|
||||
if (timer == &timer1)
|
||||
{
|
||||
@ -214,10 +227,10 @@ namespace
|
||||
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());
|
||||
CHECK_EQUAL(timer2.get_config().get_period(), timer2.get_config().get_delta());
|
||||
CHECK_EQUAL(timer1.get_config().get_period() - timer3.get_config().get_period(), timer1.get_config().get_delta());
|
||||
CHECK_EQUAL(timer4.get_config().get_period() - timer1.get_config().get_period(), timer4.get_config().get_delta());
|
||||
CHECK_EQUAL(timer5.get_config().get_period() - timer2.get_config().get_period(), timer5.get_config().get_delta());
|
||||
|
||||
// Remove a timer that is not in the list.
|
||||
active_list.remove(&timer6);
|
||||
@ -231,7 +244,7 @@ namespace
|
||||
|
||||
timer = active_list.first();
|
||||
|
||||
while (timer != ETL_NULLPTR)
|
||||
while (timer != active_list.end())
|
||||
{
|
||||
if (timer == &timer1)
|
||||
{
|
||||
@ -258,31 +271,37 @@ namespace
|
||||
}
|
||||
|
||||
// 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());
|
||||
CHECK_EQUAL(timer2.get_config().get_period(), timer2.get_config().get_delta());
|
||||
CHECK_EQUAL(timer1.get_config().get_period() - timer3.get_config().get_period(), timer1.get_config().get_delta());
|
||||
CHECK_EQUAL(timer4.get_config().get_period() - timer1.get_config().get_period(), timer4.get_config().get_delta());
|
||||
CHECK_EQUAL(timer5.get_config().get_period() - timer2.get_config().get_period(), timer5.get_config().get_delta());
|
||||
|
||||
// Clear the list.
|
||||
active_list.clear();
|
||||
|
||||
CHECK_TRUE(active_list.empty());
|
||||
CHECK_TRUE(active_list.first() == ETL_NULLPTR);
|
||||
CHECK_TRUE(active_list.first() == active_list.end());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_triggered_list)
|
||||
TEST(test_timer_triggered_list)
|
||||
{
|
||||
etl::timer_config timer1;
|
||||
etl::timer_config timer2;
|
||||
etl::timer_config timer3;
|
||||
etl::timer_config timer4;
|
||||
etl::timer_config timer5;
|
||||
constexpr etl::timer_config timer1_config(100, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer2_config(65, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer3_config(85, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer4_config(130, etl::timer::mode::Repeating);
|
||||
constexpr etl::timer_config timer5_config(85, etl::timer::mode::Repeating);
|
||||
|
||||
etl::timer_triggered_list triggered_list;
|
||||
etl::timer_node timer1{timer1_config};
|
||||
etl::timer_node timer2{timer2_config};
|
||||
etl::timer_node timer3{timer3_config};
|
||||
etl::timer_node timer4{timer4_config};
|
||||
etl::timer_node timer5{timer5_config};
|
||||
|
||||
etl::private_timer::timer_triggered_list triggered_list;
|
||||
|
||||
CHECK_TRUE(triggered_list.empty());
|
||||
CHECK_TRUE(triggered_list.first() == ETL_NULLPTR);
|
||||
CHECK_TRUE(triggered_list.first() == triggered_list.end());
|
||||
|
||||
// Add the timers to the list.
|
||||
triggered_list.insert(&timer1);
|
||||
@ -295,7 +314,7 @@ namespace
|
||||
CHECK_TRUE(triggered_list.first() == &timer1);
|
||||
|
||||
// The timers should be in the order they were added.
|
||||
etl::timer_config* timer = triggered_list.first();
|
||||
etl::timer_node* timer = triggered_list.first();
|
||||
|
||||
CHECK_EQUAL(&timer1, timer);
|
||||
timer = triggered_list.next(timer);
|
||||
@ -307,13 +326,13 @@ namespace
|
||||
timer = triggered_list.next(timer);
|
||||
CHECK_EQUAL(&timer5, timer);
|
||||
timer = triggered_list.next(timer);
|
||||
CHECK_EQUAL(ETL_NULLPTR, timer);
|
||||
CHECK_EQUAL(triggered_list.end(), timer);
|
||||
|
||||
// Clear the list.
|
||||
triggered_list.clear();
|
||||
|
||||
CHECK_TRUE(triggered_list.empty());
|
||||
CHECK_TRUE(triggered_list.first() == ETL_NULLPTR);
|
||||
CHECK_TRUE(triggered_list.first() == triggered_list.end());
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
85
test/test_timer_node.cpp
Normal file
85
test/test_timer_node.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/******************************************************************************
|
||||
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_node.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
SUITE(test_timer_config_and_node)
|
||||
{
|
||||
//*************************************************************************
|
||||
TEST(test_timer_config)
|
||||
{
|
||||
constexpr etl::timer_config config1(100U, etl::timer::mode::Repeating);
|
||||
CHECK_EQUAL(100U, config1.get_period());
|
||||
CHECK_EQUAL(100U, config1.get_delta());
|
||||
CHECK_EQUAL(etl::timer::mode::Repeating, config1.get_mode());
|
||||
|
||||
etl::timer_config config2(200U, etl::timer::mode::Single_Shot);
|
||||
CHECK_EQUAL(200U, config2.get_period());
|
||||
CHECK_EQUAL(200U, config2.get_delta());
|
||||
CHECK_EQUAL(etl::timer::mode::Single_Shot, config2.get_mode());
|
||||
|
||||
etl::timer_config config3(config2);
|
||||
CHECK_EQUAL(config2.get_period(), config3.get_period());
|
||||
CHECK_EQUAL(config2.get_delta(), config3.get_delta());
|
||||
CHECK_EQUAL(etl::timer::mode::Single_Shot, config2.get_mode());
|
||||
|
||||
etl::timer_config config4 = etl::timer_config(500U, etl::timer::mode::Repeating);
|
||||
CHECK_EQUAL(500U, config4.get_period());
|
||||
CHECK_EQUAL(500U, config4.get_delta());
|
||||
CHECK_EQUAL(etl::timer::mode::Repeating, config4.get_mode());
|
||||
|
||||
config2.clear();
|
||||
CHECK_EQUAL(etl::timer::state::Inactive, config2.get_period());
|
||||
CHECK_EQUAL(etl::timer::state::Inactive, config2.get_delta());
|
||||
CHECK_EQUAL(etl::timer::mode::Repeating, config2.get_mode());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_timer_node)
|
||||
{
|
||||
constexpr etl::timer_config config1(100U, etl::timer::mode::Repeating);
|
||||
|
||||
etl::timer_node node1(config1);
|
||||
etl::timer_node node2(node1);
|
||||
|
||||
const etl::timer_config& config1_ref = node1.get_config();
|
||||
|
||||
CHECK_EQUAL(config1.get_period(), node1.get_config().get_period());
|
||||
CHECK_EQUAL(config1.get_delta(), node1.get_config().get_delta());
|
||||
CHECK_EQUAL(config1.get_mode(), node1.get_config().get_mode());
|
||||
|
||||
CHECK_EQUAL(node1.get_config().get_period(), node2.get_config().get_period());
|
||||
CHECK_EQUAL(node1.get_config().get_delta(), node2.get_config().get_delta());
|
||||
CHECK_EQUAL(node1.get_config().get_mode(), node2.get_config().get_mode());
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
@ -3559,7 +3559,8 @@
|
||||
<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\private\timer_lists.h" />
|
||||
<ClInclude Include="..\..\include\etl\timer_node.h" />
|
||||
<ClInclude Include="..\..\include\etl\invoke.h" />
|
||||
<ClInclude Include="..\..\include\etl\lcm.h" />
|
||||
<ClInclude Include="..\..\include\etl\math.h" />
|
||||
@ -11450,7 +11451,8 @@
|
||||
<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_timer_lists.cpp" />
|
||||
<ClCompile Include="..\test_timer_node.cpp" />
|
||||
<ClCompile Include="..\test_to_arithmetic.cpp" />
|
||||
<ClCompile Include="..\test_to_arithmetic_u16.cpp" />
|
||||
<ClCompile Include="..\test_to_arithmetic_u32.cpp" />
|
||||
|
||||
@ -1569,9 +1569,12 @@
|
||||
<ClInclude Include="..\..\include\etl\format.h">
|
||||
<Filter>UnitTest++\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\timer_config.h">
|
||||
<ClInclude Include="..\..\include\etl\timer_node.h">
|
||||
<Filter>ETL\Frameworks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\include\etl\private\timer_lists.h">
|
||||
<Filter>ETL\Private</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\test_string_char.cpp">
|
||||
@ -3842,8 +3845,11 @@
|
||||
<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 Include="..\test_timer_node.cpp">
|
||||
<Filter>Tests\Callback Timers</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\test_timer_lists.cpp">
|
||||
<Filter>Tests\Callback Timers</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user