Please consider following code:
struct timer_s {
timer_s(void (*func)(void *), void *data, uint64_t period = 0)
: func(func), data(data), period(period) {}
void (*func)(void *);
void *data;
uint64_t period;
};
static std::map<uint64_t, std::unique_ptr<timer_s>> TIMERS;
extern "C" void default_machine_timer_interrupt_handler(void) {
auto mtime = interrupt_timer_mtime_get();
if (TIMERS.empty()) {
interrupt_timer_disable();
return;
}
auto it = TIMERS.begin();
it->second->func(it->second->data);
if (it->second->period) std::swap(TIMERS[mtime + it->second->period], it->second);
TIMERS.erase(it);
if (!TIMERS.empty()) {
interrupt_timer_cmp_set(TIMERS.begin()->first);
return;
}
interrupt_timer_disable();
}
void create_timer(void (*fun)(void *), void *data, uint32_t usec, timer_type_t timer_type) {
auto when = interrupt_timer_mtime_get() + usec;
auto enable = false;
if (TIMERS.empty()) enable = true;
TIMERS.insert(std::make_pair(when, std::unique_ptr<timer_s>(new timer_s(
fun, data, timer_type == TIMER_REPEAT ? usec : 0))));
interrupt_timer_cmp_set(TIMERS.begin()->first);
if (enable) interrupt_timer_enable();
}
My question is regarding using advanced solutions like STL in ISR. For the sake of discussion lets leave performance(complicated operations in interrupt context).
default_machine_timer_interrupt_handler
is run from ISR and create_timer
from main context. It works just fine. But why? Map TIMERS
is not volatile and optimization is on. Is it just a coincidence? When I have to tag value as volatile
?