/** * \brief Executes the callback of a timer. * * Then, if the callback returns \c true, the timer is rescheduled, * otherwise it is discarded. * * Does nothing if the timer is already finished. * * \param timer The timer to execute. */ void LuaContext::do_timer_callback(const TimerPtr& timer) { Debug::check_assertion(timer->is_finished(), "This timer is still running"); auto it = timers.find(timer); if (it != timers.end() && !it->second.callback_ref.is_empty()) { ScopedLuaRef& callback_ref = it->second.callback_ref; push_ref(l, callback_ref); const bool success = call_function(0, 1, "timer callback"); bool repeat = false; if (success) { repeat = lua_isboolean(l, -1) && lua_toboolean(l, -1); lua_pop(l, 1); } if (repeat) { // The callback returned true: reschedule the timer. timer->set_expiration_date(timer->get_expiration_date() + timer->get_initial_duration()); if (timer->is_finished()) { // Already finished: this is possible if the duration is smaller than // the main loop stepsize. do_timer_callback(timer); } } else { callback_ref.clear(); timers_to_remove.push_back(timer); } } }