Как выглядят костыли в коде (#2)
Привет.
По свежим следам, добавлю сюда заметку про недавнее изменение в коде FB3.
Вкратце о проблеме.
1. Есть объект со счетчиком ссылок (класс rem_port).
2. Этот объект управляется через смарт указатель. И, по идее, проблем быть не должно.
3. Тем не менее у него проблема с управлением времени жизни. Дважды удаляется в многопоточной среде.
4. Потому что конструктор rem_port, за каким-то …, вызывает addRef. И этот инкремент нужно где-то компенсировать однократным вызовом release.
Если я все правильно понял, багу заложили около 12 лет назад. Когда в rem_port добавили счетчик ссылок. Но это так, для ориентира.
Что делает этот патч. Он делает добавляет монопольность этого однократного вызова release.
bool releasePort()
{
Firebird::RefMutexEnsureUnlock portGuard(*port_sync, FB_FUNCTION);
const bool locked = portGuard.tryEnter();
fb_assert(locked);
fb_assert(!(port_flags & PORT_released));
if (port_flags & PORT_released)
return false;
port_flags |= PORT_released;
release();
return true;
}
При этом для блокировки он использует guard (*port_sync) и флаг (port_flags), которые находятся в самом защищаемом объекте.
Я считаю — это гениально.
Нет, правда, аплодирую стоя.
