29#ifndef ETL_MESSAGE_TIMER_ATOMIC_INCLUDED
30#define ETL_MESSAGE_TIMER_ATOMIC_INCLUDED
37#include "message_bus.h"
38#include "message_router.h"
39#include "message_types.h"
41#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_, etl::imessage_router& router_, uint32_t period_,
bool repeating_,
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);
112 remove_callback.call_if(timer.id);
117 new (&timer) timer_data();
130 void enable(
bool state_)
138 bool is_running()
const
152 for (
int i = 0; i < MAX_TIMERS; ++i)
154 new (&timer_array[i]) timer_data();
157 registered_timers = 0U;
166 bool tick(uint32_t count)
170 if (process_semaphore == 0U)
173 bool has_active = !active_list.empty();
177 while (has_active && (count >= active_list.front().delta))
179 timer_data& timer = active_list.front();
181 count -= timer.delta;
183 active_list.remove(timer.id,
true);
184 remove_callback.call_if(timer.id);
186 if (timer.p_router != ETL_NULLPTR)
188 timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
193 timer.delta = timer.period;
194 active_list.insert(timer.id);
195 insert_callback.call_if(timer.id);
198 has_active = !active_list.empty();
204 active_list.front().delta -= count;
218 bool start(etl::timer::id::type id_,
bool immediate_ =
false)
223 if (id_ != etl::timer::id::NO_TIMER)
225 timer_data& timer = timer_array[id_];
228 if (timer.id != etl::timer::id::NO_TIMER)
231 if (timer.period != etl::timer::state::Inactive)
234 if (timer.is_active())
236 active_list.remove(timer.id,
false);
237 remove_callback.call_if(timer.id);
240 timer.delta = immediate_ ? 0U : timer.period;
241 active_list.insert(timer.id);
242 insert_callback.call_if(timer.id);
256 bool stop(etl::timer::id::type id_)
261 if (id_ != etl::timer::id::NO_TIMER)
263 timer_data& timer = timer_array[id_];
266 if (timer.id != etl::timer::id::NO_TIMER)
268 if (timer.is_active())
271 active_list.remove(timer.id,
false);
272 remove_callback.call_if(timer.id);
286 bool set_period(etl::timer::id::type id_, uint32_t period_)
290 timer_array[id_].period = period_;
300 bool set_mode(etl::timer::id::type id_,
bool repeating_)
304 timer_array[id_].repeating = repeating_;
314 bool has_active_timer()
const
317 bool result = !active_list.empty();
328 uint32_t time_to_next()
const
330 uint32_t delta =
static_cast<uint32_t
>(etl::timer::interval::No_Active_Interval);
333 if (!active_list.empty())
335 delta = active_list.front().delta;
345 void set_insert_callback(event_callback_type insert_)
347 insert_callback = insert_;
353 void set_remove_callback(event_callback_type remove_)
355 remove_callback = remove_;
359 void clear_insert_callback()
361 insert_callback.clear();
365 void clear_remove_callback()
367 remove_callback.clear();
378 : p_message(ETL_NULLPTR)
379 , p_router(ETL_NULLPTR)
381 , delta(etl::timer::state::Inactive)
382 , destination_router_id(etl::imessage_bus::ALL_MESSAGE_ROUTERS)
383 , id(etl::timer::id::NO_TIMER)
384 , previous(etl::timer::id::NO_TIMER)
385 , next(etl::timer::id::NO_TIMER)
391 timer_data(etl::timer::id::type id_,
const etl::imessage& message_, etl::imessage_router& irouter_, uint32_t period_,
bool repeating_,
392 etl::message_router_id_t destination_router_id_ = etl::imessage_bus::ALL_MESSAGE_ROUTERS)
393 : p_message(&message_)
394 , p_router(&irouter_)
396 , delta(etl::timer::state::Inactive)
397 , destination_router_id(destination_router_id_)
399 , previous(etl::timer::id::NO_TIMER)
400 , next(etl::timer::id::NO_TIMER)
401 , repeating(repeating_)
408 bool is_active()
const
410 return delta != etl::timer::state::Inactive;
418 delta = etl::timer::state::Inactive;
421 const etl::imessage* p_message;
422 etl::imessage_router* p_router;
425 etl::message_router_id_t destination_router_id;
426 etl::timer::id::type id;
427 uint_least8_t previous;
434 timer_data(
const timer_data& other);
435 timer_data& operator=(
const timer_data& other);
441 imessage_timer_atomic(timer_data*
const timer_array_,
const uint_least8_t Max_Timers)
442 : timer_array(timer_array_)
443 , active_list(timer_array_)
445 , process_semaphore(0U)
446 , registered_timers(0U)
447 , MAX_TIMERS(Max_Timers)
454 ~imessage_timer_atomic() {}
466 timer_list(timer_data* ptimers_)
467 : head(etl::timer::id::NO_TIMER)
468 , tail(etl::timer::id::NO_TIMER)
469 , current(etl::timer::id::NO_TIMER)
477 return head == etl::timer::id::NO_TIMER;
483 void insert(etl::timer::id::type id_)
485 timer_data& timer = ptimers[id_];
487 if (head == etl::timer::id::NO_TIMER)
492 timer.previous = etl::timer::id::NO_TIMER;
493 timer.next = etl::timer::id::NO_TIMER;
498 etl::timer::id::type test_id =
begin();
500 while (test_id != etl::timer::id::NO_TIMER)
502 timer_data& test = ptimers[test_id];
505 if (timer.delta <= test.delta)
513 timer.previous = test.previous;
514 test.previous = timer.id;
515 timer.next = test.id;
518 test.delta -= timer.delta;
520 if (timer.previous != etl::timer::id::NO_TIMER)
522 ptimers[timer.previous].next = timer.id;
528 timer.delta -= test.delta;
531 test_id = next(test_id);
535 if (test_id == etl::timer::id::NO_TIMER)
538 ptimers[tail].next = timer.id;
539 timer.previous = tail;
540 timer.next = etl::timer::id::NO_TIMER;
547 void remove(etl::timer::id::type id_,
bool has_expired)
549 timer_data& timer = ptimers[id_];
557 ptimers[timer.previous].next = timer.next;
562 tail = timer.previous;
566 ptimers[timer.next].previous = timer.previous;
572 if (timer.next != etl::timer::id::NO_TIMER)
574 ptimers[timer.next].delta += timer.delta;
578 timer.previous = etl::timer::id::NO_TIMER;
579 timer.next = etl::timer::id::NO_TIMER;
580 timer.delta = etl::timer::state::Inactive;
586 return ptimers[head];
590 const timer_data& front()
const
592 return ptimers[head];
596 etl::timer::id::type
begin()
603 etl::timer::id::type previous(etl::timer::id::type last)
605 current = ptimers[last].previous;
610 etl::timer::id::type next(etl::timer::id::type last)
612 current = ptimers[last].next;
619 etl::timer::id::type
id =
begin();
621 while (
id != etl::timer::id::NO_TIMER)
623 timer_data& timer = ptimers[id];
625 timer.next = etl::timer::id::NO_TIMER;
628 head = etl::timer::id::NO_TIMER;
629 tail = etl::timer::id::NO_TIMER;
630 current = etl::timer::id::NO_TIMER;
635 etl::timer::id::type head;
636 etl::timer::id::type tail;
637 etl::timer::id::type current;
639 timer_data*
const ptimers;
643 timer_data*
const timer_array;
646 timer_list active_list;
649 mutable TSemaphore process_semaphore;
650 uint_least8_t registered_timers;
652 event_callback_type insert_callback;
653 event_callback_type remove_callback;
657 const uint_least8_t MAX_TIMERS;
663 template <u
int_least8_t Max_Timers,
typename TSemaphore>
664 class message_timer_atomic :
public etl::imessage_timer_atomic<TSemaphore>
668 ETL_STATIC_ASSERT(Max_Timers <= 254,
"No more than 254 timers are allowed");
673 message_timer_atomic()
674 : imessage_timer_atomic<TSemaphore>(timer_array, Max_Timers)
680 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:2344
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition iterator.h:967