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"
52 template <
typename TSemaphore>
53 class imessage_timer_atomic
60 etl::timer::id::type register_timer(
const etl::imessage& message_,
64 etl::message_router_id_t destination_router_id_ = etl::imessage_router::ALL_MESSAGE_ROUTERS)
66 etl::timer::id::type
id = etl::timer::id::NO_TIMER;
68 bool is_space = (registered_timers < MAX_TIMERS);
73 if (!router_.is_null_router())
76 for (uint_least8_t i = 0U; i < MAX_TIMERS; ++i)
78 timer_data& timer = timer_array[i];
80 if (timer.id == etl::timer::id::NO_TIMER)
83 new (&timer) timer_data(i, message_, router_, period_, repeating_, destination_router_id_);
98 bool unregister_timer(etl::timer::id::type id_)
102 if (id_ != etl::timer::id::NO_TIMER)
104 timer_data& timer = timer_array[id_];
106 if (timer.id != etl::timer::id::NO_TIMER)
108 if (timer.is_active())
111 active_list.remove(timer.id,
true);
116 new (&timer) timer_data();
129 void enable(
bool state_)
137 bool is_running()
const
151 for (
int i = 0; i < MAX_TIMERS; ++i)
153 new (&timer_array[i]) timer_data();
156 registered_timers = 0U;
165 bool tick(uint32_t count)
169 if (process_semaphore == 0U)
172 bool has_active = !active_list.empty();
176 while (has_active && (count >= active_list.front().delta))
178 timer_data& timer = active_list.front();
180 count -= timer.delta;
182 active_list.remove(timer.id,
true);
184 if (timer.p_router != ETL_NULLPTR)
186 timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
191 timer.delta = timer.period;
192 active_list.insert(timer.id);
195 has_active = !active_list.empty();
201 active_list.front().delta -= count;
215 bool start(etl::timer::id::type id_,
bool immediate_ =
false)
220 if (id_ != etl::timer::id::NO_TIMER)
222 timer_data& timer = timer_array[id_];
225 if (timer.id != etl::timer::id::NO_TIMER)
228 if (timer.period != etl::timer::state::INACTIVE)
231 if (timer.is_active())
233 active_list.remove(timer.id,
false);
236 timer.delta = immediate_ ? 0U : timer.period;
237 active_list.insert(timer.id);
251 bool stop(etl::timer::id::type id_)
256 if (id_ != etl::timer::id::NO_TIMER)
258 timer_data& timer = timer_array[id_];
261 if (timer.id != etl::timer::id::NO_TIMER)
263 if (timer.is_active())
266 active_list.remove(timer.id,
false);
280 bool set_period(etl::timer::id::type id_, uint32_t period_)
284 timer_array[id_].period = period_;
294 bool set_mode(etl::timer::id::type id_,
bool repeating_)
298 timer_array[id_].repeating = repeating_;
313 : p_message(ETL_NULLPTR)
314 , p_router(ETL_NULLPTR)
316 , delta(
etl::timer::state::INACTIVE)
317 , destination_router_id(
etl::imessage_bus::ALL_MESSAGE_ROUTERS)
318 , id(
etl::timer::id::NO_TIMER)
319 , previous(
etl::timer::id::NO_TIMER)
320 , next(
etl::timer::id::NO_TIMER)
326 timer_data(etl::timer::id::type id_,
331 etl::message_router_id_t destination_router_id_ = etl::imessage_bus::ALL_MESSAGE_ROUTERS)
332 : p_message(&message_)
333 , p_router(&irouter_)
335 , delta(
etl::timer::state::INACTIVE)
336 , destination_router_id(destination_router_id_)
338 , previous(
etl::timer::id::NO_TIMER)
339 , next(
etl::timer::id::NO_TIMER)
340 , repeating(repeating_)
347 bool is_active()
const
349 return delta != etl::timer::state::INACTIVE;
357 delta = etl::timer::state::INACTIVE;
364 etl::message_router_id_t destination_router_id;
365 etl::timer::id::type id;
366 uint_least8_t previous;
373 timer_data(
const timer_data& other);
374 timer_data& operator =(
const timer_data& other);
380 imessage_timer_atomic(timer_data*
const timer_array_,
const uint_least8_t MAX_TIMERS_)
381 : timer_array(timer_array_)
382 , active_list(timer_array_)
384 , process_semaphore(0U)
385 , registered_timers(0U)
386 , MAX_TIMERS(MAX_TIMERS_)
393 ~imessage_timer_atomic()
407 timer_list(timer_data* ptimers_)
408 : head(
etl::timer::id::NO_TIMER),
409 tail(
etl::timer::id::NO_TIMER),
410 current(
etl::timer::id::NO_TIMER),
418 return head == etl::timer::id::NO_TIMER;
424 void insert(etl::timer::id::type id_)
426 timer_data& timer = ptimers[id_];
428 if (head == etl::timer::id::NO_TIMER)
433 timer.previous = etl::timer::id::NO_TIMER;
434 timer.next = etl::timer::id::NO_TIMER;
439 etl::timer::id::type test_id =
begin();
441 while (test_id != etl::timer::id::NO_TIMER)
443 timer_data& test = ptimers[test_id];
446 if (timer.delta <= test.delta)
454 timer.previous = test.previous;
455 test.previous = timer.id;
456 timer.next = test.id;
459 test.delta -= timer.delta;
461 if (timer.previous != etl::timer::id::NO_TIMER)
463 ptimers[timer.previous].next = timer.id;
469 timer.delta -= test.delta;
472 test_id = next(test_id);
476 if (test_id == etl::timer::id::NO_TIMER)
479 ptimers[tail].next = timer.id;
480 timer.previous = tail;
481 timer.next = etl::timer::id::NO_TIMER;
488 void remove(etl::timer::id::type id_,
bool has_expired)
490 timer_data& timer = ptimers[id_];
498 ptimers[timer.previous].next = timer.next;
503 tail = timer.previous;
507 ptimers[timer.next].previous = timer.previous;
513 if (timer.next != etl::timer::id::NO_TIMER)
515 ptimers[timer.next].delta += timer.delta;
519 timer.previous = etl::timer::id::NO_TIMER;
520 timer.next = etl::timer::id::NO_TIMER;
521 timer.delta = etl::timer::state::INACTIVE;
527 return ptimers[head];
531 etl::timer::id::type
begin()
538 etl::timer::id::type previous(etl::timer::id::type last)
540 current = ptimers[last].previous;
545 etl::timer::id::type next(etl::timer::id::type last)
547 current = ptimers[last].next;
554 etl::timer::id::type
id =
begin();
556 while (
id != etl::timer::id::NO_TIMER)
558 timer_data& timer = ptimers[id];
560 timer.next = etl::timer::id::NO_TIMER;
563 head = etl::timer::id::NO_TIMER;
564 tail = etl::timer::id::NO_TIMER;
565 current = etl::timer::id::NO_TIMER;
570 etl::timer::id::type head;
571 etl::timer::id::type tail;
572 etl::timer::id::type current;
574 timer_data*
const ptimers;
578 timer_data*
const timer_array;
581 timer_list active_list;
584 TSemaphore process_semaphore;
585 uint_least8_t registered_timers;
589 const uint_least8_t MAX_TIMERS;
595 template <u
int_least8_t MAX_TIMERS_,
typename TSemaphore>
596 class message_timer_atomic :
public etl::imessage_timer_atomic<TSemaphore>
600 ETL_STATIC_ASSERT(MAX_TIMERS_ <= 254,
"No more than 254 timers are allowed");
605 message_timer_atomic()
606 : imessage_timer_atomic<TSemaphore>(timer_array, MAX_TIMERS_)
612 typename etl::imessage_timer_atomic<TSemaphore>::timer_data timer_array[MAX_TIMERS_];
This is the base of all message routers.
Definition: message_router_generator.h:121
ETL_CONSTEXPR14 TIterator remove(TIterator first, TIterator last, const T &value)
Definition: algorithm.h:1934
bitset_ext
Definition: absolute.h:38
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition: iterator.h:931