[Server] Fix iterating killed timers when kill() called in the callback

Instance new timers before new tick
sol2-server-rewrite
Koncord 7 years ago
parent 45d3b24c17
commit 1de9f30449

@ -62,7 +62,7 @@ Timer::~Timer()
void Timer::tick() void Timer::tick()
{ {
if (end) if (end || markedToDelete)
return; return;
const auto duration = chrono::system_clock::now().time_since_epoch(); const auto duration = chrono::system_clock::now().time_since_epoch();
@ -81,6 +81,11 @@ void Timer::tick()
} }
} }
void Timer::kill()
{
markedToDelete = true;
}
void TimerController::Init(LuaState &lua) void TimerController::Init(LuaState &lua)
{ {
sol::table timerTable = lua.getState()->create_table("TimerCtrl"); sol::table timerTable = lua.getState()->create_table("TimerCtrl");
@ -96,22 +101,37 @@ void TimerController::Init(LuaState &lua)
std::shared_ptr<Timer> TimerController::create(sol::environment env, sol::function callback, long msec, sol::table args) std::shared_ptr<Timer> TimerController::create(sol::environment env, sol::function callback, long msec, sol::table args)
{ {
timers.emplace_back(new Timer(env, callback, msec, args)); newTimersQueue.emplace_back(new Timer(env, callback, msec, args));
return timers.back(); return newTimersQueue.back();
} }
void TimerController::kill(const std::shared_ptr<Timer> &timer) void TimerController::kill(const std::shared_ptr<Timer> &timer)
{ {
auto it = find(timers.begin(), timers.end(), timer); LOG_MESSAGE_SIMPLE(Log::LOG_TRACE, "Timer %p marked for deletion\n", timer.get());
if (it != timers.end()) timer->kill();
{ haveMarkedToDeletion = true;
LOG_MESSAGE_SIMPLE(Log::LOG_TRACE, "Timer %p killed\n", timer.get());
timers.erase(it);
}
} }
void TimerController::tick() void TimerController::tick()
{ {
if (haveMarkedToDeletion)
{
size_t deleted = timers.size();
haveMarkedToDeletion = false;
timers.erase(remove_if(timers.begin(), timers.end(), [](const std::shared_ptr<Timer> &timer) {
return timer->isMarkedToDelete();
}), timers.end());
deleted -= timers.size();
LOG_MESSAGE_SIMPLE(Log::LOG_TRACE, "Deleted %d timers\n", deleted);
}
if(!newTimersQueue.empty())
{
timers.insert(timers.begin(), make_move_iterator(newTimersQueue.begin()), make_move_iterator(newTimersQueue.end()));
LOG_MESSAGE_SIMPLE(Log::LOG_TRACE, "Created %d timers\n", newTimersQueue.size());
newTimersQueue.clear();
}
for (auto &timer : timers) for (auto &timer : timers)
{ {
timer->tick(); timer->tick();

@ -24,12 +24,15 @@ public:
protected: protected:
Timer(sol::environment &env, sol::function &callback, long msec, sol::table &args); Timer(sol::environment &env, sol::function &callback, long msec, sol::table &args);
void tick(); void tick();
void kill();
bool isMarkedToDelete() const { return markedToDelete; }
private: private:
double startTime, targetMsec; double startTime, targetMsec;
sol::function callback; sol::function callback;
sol::table data; sol::table data;
sol::environment env; sol::environment env;
bool end; bool end;
bool markedToDelete;
}; };
class TimerController class TimerController
@ -44,5 +47,7 @@ public:
void tick(); void tick();
private: private:
std::vector<std::shared_ptr<Timer>> timers; std::vector<std::shared_ptr<Timer>> timers;
std::vector<std::shared_ptr<Timer>> newTimersQueue;
bool haveMarkedToDeletion;
}; };

Loading…
Cancel
Save