rusefi-full/firmware/controllers/algo/event_queue.cpp

90 lines
2.1 KiB
C++

/**
* @file event_queue.cpp
* This is a data structure which keeps track of all pending events
* Implemented as a linked list, which is fine since the number of
* pending events is pretty low
* todo: MAYBE migrate to a better data structure, but that's low priority
*
* this data structure is NOT thread safe
*
* @date Apr 17, 2014
* @author Andrey Belomutskiy, (c) 2012-2014
*/
#include "event_queue.h"
#include "efitime.h"
#include "utlist.h"
EventQueue::EventQueue() {
head = NULL;
}
void EventQueue::insertTask(scheduling_s *scheduling, uint64_t nowUs, int delayUs, schfunc_t callback, void *param) {
if (callback == NULL)
firmwareError("NULL callback");
uint64_t time = nowUs + delayUs;
scheduling->momentUs = time;
#if EFI_SIGNAL_EXECUTOR_ONE_TIMER
scheduling->callback = callback;
scheduling->param = param;
#endif
scheduling_s * elt;
LL_FOREACH(head, elt)
{
if (elt == scheduling) {
firmwareError("re-adding element");
return;
}
}
LL_PREPEND(head, scheduling);
}
void EventQueue::insertTask(scheduling_s *scheduling, int delayUs, schfunc_t callback, void *param) {
insertTask(scheduling, getTimeNowUs(), delayUs, callback, param);
}
/**
* Get the timestamp of the soonest pending action
*/
uint64_t EventQueue::getNextEventTime(uint64_t nowUs) {
scheduling_s * elt;
// this is a large value which is expected to be larger than any real time
uint64_t result = EMPTY_QUEUE;
LL_FOREACH(head, elt)
{
if (elt->momentUs <= nowUs) {
// todo: I am not so sure about this branch
continue;
}
if (elt->momentUs < result)
result = elt->momentUs;
}
return result;
}
/**
* Invoke all pending actions prior to specified timestamp
*/
void EventQueue::executeAll(uint64_t now) {
scheduling_s * elt, *tmp;
// here we need safe iteration because we are removing elements
LL_FOREACH_SAFE(head, elt, tmp)
{
if (elt->momentUs <= now) {
LL_DELETE(head, elt);
#if EFI_SIGNAL_EXECUTOR_ONE_TIMER
elt->callback(elt->param);
#endif /* EFI_SIGNAL_EXECUTOR_ONE_TIMER */
}
}
}
void EventQueue::clear(void) {
head = NULL;
}