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?
