Пример #1
0
/**
 * \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);
    }
  }
}
Пример #2
0
/**
 * \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(Timer& timer) {

  Debug::check_assertion(timer.is_finished(), "This timer is still running");

  const std::map<Timer*, LuaTimerData>::iterator it = timers.find(&timer);
  if (it != timers.end() && it->second.callback_ref != LUA_REFNIL) {
    const int callback_ref = it->second.callback_ref;
    push_callback(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 {
      cancel_callback(callback_ref);
      it->second.callback_ref = LUA_REFNIL;
      timers_to_remove.push_back(&timer);
    }
  }
}
Пример #3
0
/**
 * \brief Updates all timers currently running for this script.
 */
void LuaContext::update_timers() {

  // Update all timers.
  for (const auto& kvp: timers) {

    const TimerPtr& timer = kvp.first;
    const ScopedLuaRef& callback_ref = kvp.second.callback_ref;
    if (!callback_ref.is_empty()) {
      // The timer is not being removed: update it.
      timer->update();
      if (timer->is_finished()) {
        do_timer_callback(timer);
      }
    }
  }

  // Destroy the ones that should be removed.
  for (const TimerPtr& timer: timers_to_remove) {

    const auto& it = timers.find(timer);
    if (it != timers.end()) {
      timers.erase(it);

      Debug::check_assertion(timers.find(timer) == timers.end(),
          "Failed to remove timer");
    }
  }
  timers_to_remove.clear();
}
Пример #4
0
/**
 * \brief Updates all timers currently running for this script.
 */
void LuaContext::update_timers() {

  // Update all timers.
  std::map<Timer*, LuaTimerData>::iterator it;
  for (it = timers.begin(); it != timers.end(); ++it) {

    Timer* timer = it->first;
    int callback_ref = it->second.callback_ref;
    if (callback_ref != LUA_REFNIL) {
      // The timer is not being removed: update it.
      timer->update();
      if (timer->is_finished()) {
        do_timer_callback(*timer);
      }
    }
  }

  // Destroy the ones that should be removed.
  std::list<Timer*>::iterator it2;
  for (it2 = timers_to_remove.begin(); it2 != timers_to_remove.end(); ++it2) {

    Timer* timer = *it2;
    it = timers.find(timer);
    if (it != timers.end()) {
      if (!timer->is_finished()) {
        cancel_callback(it->second.callback_ref);
      }
      timers.erase(it);
      RefCountable::unref(timer);

      Debug::check_assertion(timers.find(timer) == timers.end(),
          "Failed to remove timer");
    }
  }
  timers_to_remove.clear();
}