Как выглядят костыли в коде (#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), которые находятся в самом защищаемом объекте.
Я считаю — это гениально.
Нет, правда, аплодирую стоя.