Loading...
bonev_st avatar bonev_st 13 Точки

Малък фикс в TimerMgr

Проблем: Когато таймера е стопиран в предишния цикъл на main loop-a на Engine чрез TimerClient::stopTimer() и изтече в този - ще се генерира onTimerTimeout с Id на таймер който вече е спрян, също така ще намали броя на итерации в цикъл

for(auto& [id, data] : m_TimerMap) {
        data.m_Remaining -= elapsed_ms;
        if (0 > data.m_Remaining) {
            onTimerTimeout(id, data);
        }
  }

Вариант 1:

 Предлагам малка промяна в реда на TimerMgr::process() метода - removeTimers() да се премети в началото на фунията.

Вариант 2:

 В stopTimer и в detachTimerClient да се извиква removeTimers() преди края на методите.

 

Тагове:
2
C++ Applications Development
j.petrov_90 avatar j.petrov_90 373 Точки

Привет, bonev_st,

Не съм го пробвал с код, но като го "разиграх на ум" наистина достигнах до посочения проблем от теб.

Вариант 1 ми се струва добро предложение.
Жив и здрав :)

Вариант 2 или не го разчитам правилно или мисля, че би имало проблем с него.
Ако чрез stopTimer директно триеш таймера от map-а с removeTimers() ще попаднеш в проблема, заради който съществува онзи std::set както и функцията removeTimers() на първо време.

Казуса беше, че при стечение на обстоятелствана е съвсем нормално в един дълъг call stack да имаш 2 извикватия на stopTimer с едно и също id.
И двете са били валидни в момента на извикването им.
Резултата е, че единият би изтрил таймера, а за другия би се хвърлило грешка - "такъв таймер няма".

Разбира се, може и да не съм разбрал правилно.

Поздрави 

1
MartinBG avatar MartinBG 4803 Точки

При вариант 1 може да изпаднем в следната ситуация:

- oneshot таймер изтича по време на цикъла и съответно се добавя в сета за изтриване, но не е изтрит (защото removeTimers() е в началото на TimerManager::process())

- ако в следващия цикъл от Game или някъде другаде стартираме нов таймер със същото ID, този таймер ще бъде създаден успешно (защото isActiveTimerId ще върне false), но ще бъде изтрит при първото извикване на TimerManager::process(), защото id-то му е маркирано за изтриване

Вариант за решаване на този проблем е да извикваме removeTimers() 2 пъти в TimerManager::process() - един път в началото (премахваме спрените таймери) и веднъж в края на метода (премахваме изтеклите таймери).

2
07/11/2021 21:25:14
bonev_st avatar bonev_st 13 Точки

Да, абасолютно си прав!

2
j.petrov_90 avatar j.petrov_90 373 Точки

Супер сте, колеги :)

1
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.