29#ifndef ETL_MESSAGE_TIMER_ATOMIC_INCLUDED
30#define ETL_MESSAGE_TIMER_ATOMIC_INCLUDED
34#include "message_types.h"
36#include "message_router.h"
37#include "message_bus.h"
38#include "static_assert.h"
53 template <
typename TSemaphore>
54 class imessage_timer_atomic
58 typedef etl::delegate<void(etl::timer::id::type)> event_callback_type;
63 etl::timer::id::type register_timer(
const etl::imessage& message_,
64 etl::imessage_router& router_,
67 etl::message_router_id_t destination_router_id_ = etl::imessage_router::ALL_MESSAGE_ROUTERS)
69 etl::timer::id::type
id = etl::timer::id::NO_TIMER;
71 bool is_space = (registered_timers < MAX_TIMERS);
76 if (!router_.is_null_router())
79 for (uint_least8_t i = 0U; i < MAX_TIMERS; ++i)
81 timer_data& timer = timer_array[i];
83 if (timer.id == etl::timer::id::NO_TIMER)
86 new (&timer) timer_data(i, message_, router_, period_, repeating_, destination_router_id_);
101 bool unregister_timer(etl::timer::id::type id_)
105 if (id_ != etl::timer::id::NO_TIMER)
107 timer_data& timer = timer_array[id_];
109 if (timer.id != etl::timer::id::NO_TIMER)
111 if (timer.is_active())
114 active_list.remove(timer.id,
true);
115 remove_callback.call_if(timer.id);
120 new (&timer) timer_data();
133 void enable(
bool state_)
141 bool is_running()
const
155 for (
int i = 0; i < MAX_TIMERS; ++i)
157 new (&timer_array[i]) timer_data();
160 registered_timers = 0U;
169 bool tick(uint32_t count)
173 if (process_semaphore == 0U)
176 bool has_active = !active_list.empty();
180 while (has_active && (count >= active_list.front().delta))
182 timer_data& timer = active_list.front();
184 count -= timer.delta;
186 active_list.remove(timer.id,
true);
187 remove_callback.call_if(timer.id);
189 if (timer.p_router != ETL_NULLPTR)
191 timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
196 timer.delta = timer.period;
197 active_list.insert(timer.id);
198 insert_callback.call_if(timer.id);
201 has_active = !active_list.empty();
207 active_list.front().delta -= count;
221 bool start(etl::timer::id::type id_,
bool immediate_ =
false)
226 if (id_ != etl::timer::id::NO_TIMER)
228 timer_data& timer = timer_array[id_];
231 if (timer.id != etl::timer::id::NO_TIMER)
234 if (timer.period != etl::timer::state::Inactive)
237 if (timer.is_active())
239 active_list.remove(timer.id,
false);
240 remove_callback.call_if(timer.id);
243 timer.delta = immediate_ ? 0U : timer.period;
244 active_list.insert(timer.id);
245 insert_callback.call_if(timer.id);
259 bool stop(etl::timer::id::type id_)
264 if (id_ != etl::timer::id::NO_TIMER)
266 timer_data& timer = timer_array[id_];
269 if (timer.id != etl::timer::id::NO_TIMER)
271 if (timer.is_active())
274 active_list.remove(timer.id,
false);
275 remove_callback.call_if(timer.id);
289 bool set_period(etl::timer::id::type id_, uint32_t period_)
293 timer_array[id_].period = period_;
303 bool set_mode(etl::timer::id::type id_,
bool repeating_)
307 timer_array[id_].repeating = repeating_;
317 bool has_active_timer()
const
320 bool result = !active_list.empty();
330 uint32_t time_to_next()
const
332 uint32_t delta =
static_cast<uint32_t
>(etl::timer::interval::No_Active_Interval);
335 if (!active_list.empty())
337 delta = active_list.front().delta;
347 void set_insert_callback(event_callback_type insert_)
349 insert_callback = insert_;
355 void set_remove_callback(event_callback_type remove_)
357 remove_callback = remove_;
361 void clear_insert_callback()
363 insert_callback.clear();
367 void clear_remove_callback()
369 remove_callback.clear();
380 : p_message(ETL_NULLPTR)
381 , p_router(ETL_NULLPTR)
383 , delta(etl::timer::state::Inactive)
384 , destination_router_id(etl::imessage_bus::ALL_MESSAGE_ROUTERS)
385 , id(etl::timer::id::NO_TIMER)
386 , previous(etl::timer::id::NO_TIMER)
387 , next(etl::timer::id::NO_TIMER)
393 timer_data(etl::timer::id::type id_,
394 const etl::imessage& message_,
395 etl::imessage_router& irouter_,
398 etl::message_router_id_t destination_router_id_ = etl::imessage_bus::ALL_MESSAGE_ROUTERS)
399 : p_message(&message_)
400 , p_router(&irouter_)
402 , delta(etl::timer::state::Inactive)
403 , destination_router_id(destination_router_id_)
405 , previous(etl::timer::id::NO_TIMER)
406 , next(etl::timer::id::NO_TIMER)
407 , repeating(repeating_)
414 bool is_active()
const
416 return delta != etl::timer::state::Inactive;
424 delta = etl::timer::state::Inactive;
427 const etl::imessage* p_message;
428 etl::imessage_router* p_router;
431 etl::message_router_id_t destination_router_id;
432 etl::timer::id::type id;
433 uint_least8_t previous;
440 timer_data(
const timer_data& other);
441 timer_data& operator =(
const timer_data& other);
447 imessage_timer_atomic(timer_data*
const timer_array_,
const uint_least8_t Max_Timers)
448 : timer_array(timer_array_)
449 , active_list(timer_array_)
451 , process_semaphore(0U)
452 , registered_timers(0U)
453 , MAX_TIMERS(Max_Timers)
460 ~imessage_timer_atomic()
474 timer_list(timer_data* ptimers_)
475 : head(etl::timer::id::NO_TIMER)
476 , tail(etl::timer::id::NO_TIMER)
477 , current(etl::timer::id::NO_TIMER)
485 return head == etl::timer::id::NO_TIMER;
491 void insert(etl::timer::id::type id_)
493 timer_data& timer = ptimers[id_];
495 if (head == etl::timer::id::NO_TIMER)
500 timer.previous = etl::timer::id::NO_TIMER;
501 timer.next = etl::timer::id::NO_TIMER;
506 etl::timer::id::type test_id =
begin();
508 while (test_id != etl::timer::id::NO_TIMER)
510 timer_data& test = ptimers[test_id];
513 if (timer.delta <= test.delta)
521 timer.previous = test.previous;
522 test.previous = timer.id;
523 timer.next = test.id;
526 test.delta -= timer.delta;
528 if (timer.previous != etl::timer::id::NO_TIMER)
530 ptimers[timer.previous].next = timer.id;
536 timer.delta -= test.delta;
539 test_id = next(test_id);
543 if (test_id == etl::timer::id::NO_TIMER)
546 ptimers[tail].next = timer.id;
547 timer.previous = tail;
548 timer.next = etl::timer::id::NO_TIMER;
555 void remove(etl::timer::id::type id_,
bool has_expired)
557 timer_data& timer = ptimers[id_];
565 ptimers[timer.previous].next = timer.next;
570 tail = timer.previous;
574 ptimers[timer.next].previous = timer.previous;
580 if (timer.next != etl::timer::id::NO_TIMER)
582 ptimers[timer.next].delta += timer.delta;
586 timer.previous = etl::timer::id::NO_TIMER;
587 timer.next = etl::timer::id::NO_TIMER;
588 timer.delta = etl::timer::state::Inactive;
594 return ptimers[head];
598 const timer_data& front()
const
600 return ptimers[head];
604 etl::timer::id::type
begin()
611 etl::timer::id::type previous(etl::timer::id::type last)
613 current = ptimers[last].previous;
618 etl::timer::id::type next(etl::timer::id::type last)
620 current = ptimers[last].next;
627 etl::timer::id::type
id =
begin();
629 while (
id != etl::timer::id::NO_TIMER)
631 timer_data& timer = ptimers[id];
633 timer.next = etl::timer::id::NO_TIMER;
636 head = etl::timer::id::NO_TIMER;
637 tail = etl::timer::id::NO_TIMER;
638 current = etl::timer::id::NO_TIMER;
643 etl::timer::id::type head;
644 etl::timer::id::type tail;
645 etl::timer::id::type current;
647 timer_data*
const ptimers;
651 timer_data*
const timer_array;
654 timer_list active_list;
657 mutable TSemaphore process_semaphore;
658 uint_least8_t registered_timers;
660 event_callback_type insert_callback;
661 event_callback_type remove_callback;
665 const uint_least8_t MAX_TIMERS;
671 template <u
int_least8_t Max_Timers,
typename TSemaphore>
672 class message_timer_atomic :
public etl::imessage_timer_atomic<TSemaphore>
676 ETL_STATIC_ASSERT(Max_Timers <= 254,
"No more than 254 timers are allowed");
681 message_timer_atomic()
682 : imessage_timer_atomic<TSemaphore>(timer_array, Max_Timers)
688 typename etl::imessage_timer_atomic<TSemaphore>::timer_data timer_array[Max_Timers];
ETL_CONSTEXPR14 TIterator remove(TIterator first, TIterator last, const T &value)
Definition algorithm.h:2300
bitset_ext
Definition absolute.h:39
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition iterator.h:962