[Texts and Colors] Въпрос за TextContainer и Text
1. В предложеното на лекцията решение SDL_Texture* се пазят във vector, чиито индексите са и textId:
class TextContainer {
//...
void occupyFreeSlotIndex(int32_t &occupiedTextId);
void freeSlotIndex(int32_t textId);
//the textures we'll be drawing
std::vector<SDL_Texture*> _textures;
//...
}
Каква е причнината горното решение да е предпочетено, спрямо решение с unordered_map? Гледах лекцията отново, но явно изпускам нещо.
Например:
class TextContainer {
//..
int32_t nextTextId{0};
std::unordered_map<int32_t, SDL_Texture*> _textures;
}
=================
void TextContainer::createText(...)
//..
++nextTextId; //unique id
if (const auto&[i, success] = _textures.try_emplace(nextTextId, textTexture); success) {
outTextId = i->first;
}
//...
}
2. Забелязах, че не извикваме gRsrcMgr->unloadText(_drawParams.textId) в Text::destroy() и съответно не се изтриват ненужните текстури, т.е. липсва този код:
if (gRsrcMgr) {
gRsrcMgr->unloadText(_drawParams.textId);
}
Благодаря за подробния отговор!
Сигурен съм, че ще е полезен и за други колеги от групата!
Изглежда, че съм разбрал правилно идеята, но имплементацията ми се струва ненужно сложна, с потенциал да бъде по-бавна от такава с unordered_map заради occupyFreeSlotIndex, която е с линейна сложност, а има и сценарии, при които може да се окажем с ненужно голям вектор, пълен с nullptr, защото не е предвиден вариант за "свиването" му.
Горното в никакъв случай не трябва да се приема като критика, дори напротив, защото не би ми хрумнало да подходя към проблема по този начин и научих нещо ново. :)
Наистина, варианта с unordered_map ще има проблем ако nextTextId прелее, мине през всички отрицателни стойности и стигне отново до 0, но това са над 4 милиарда id-та и ако приложението не се очаква да генерира подобно количество стрингове за една сесия, мисля че логване на грешка при превъртане (т.е. nextTextId < 0) е достатъчна "защита".
Получи се добра дискусия :)
В заключение ще кажа, че и двата варианта са добри. Всеки си има trade-offs.
В зависимост от нуждите на приложението си човек може да прави всякакви оптимизации.
Ако ще има rapid text creation и в последствие rapid text destruction би имало логика да се имплементира shrinkToFit функция на варианта с вектор.
Човек, ако се замисли даже може да види, че това е много basic версия на това как ОС-а раздава памет от heap-a :)
А в последствие shrinkToFit би било дефрагментацията.
Накрая, но не на последно място искам да спомена, че signed integer overflow е undefined behavior.
Нямаш гаранция, че INT32_MAX + 1 == INT32_MIN
Компилаторите си прилагат custom оптимизации върху signed integer overflow.
Но от компилатор до компилатор има разлика.
Единствено unsigned integer overflow е defined.
Поздрави
Имплементацията на shrinkToFit функция няма да е лесна задача, защото ще промени индексите на текстурите, а тези индекси се ползват от нашите имиджи, т.е. ще трябва да има обратна референция от индексите на текстурите към всички имиджи, които ги ползват, за да бъдат ъпдейтнати.
Не знаех, че signed integer overflow е undefined behavior.
За който му е интресно, ето и дискусия в SO по темата.