Возврат ссылки из-под замка: идиоматический или чертовски умный?
Предположим, у вас есть структура данных, в которой значения хранятся в узлах, например стандартные карты или списки, и эта структура имеет блокировку для ее защиты. Предположим также, что типы значений (
mapped_type
для карт) достаточно сложен, чтобы у каждой был свой замок.
Итак, основная операция - захватить блокировку карты, получить (ссылку на) значение и разблокировать блокировку карты. Теперь вы можете заблокировать блокировку значения и веселиться на нем столько, сколько захотите.
Проблема - как я понимаю - в том, что вы не можете назначить ссылку - только инициализировать ее. Поэтому я предлагаю следующий вид кода, учитывая некоторый тип карты
M
с экземпляром
m
(и это мьютекс
m_mutex
):
const MappedType& mt = [this, key]() -> const MappedType& {
std::lock_guard _{m_mutex};
return m[key];
}();
Это тот случай, когда вы можете использовать
at
добавить элемент. Если вы не хотели этого делать, вы могли:
const MappedType& mt = [this, key]() -> const MappedType& {
std::lock_guard _{m_mutex};
M::const_iterator it = m.find(key);
if (m.cend() != it)
return it->second;
else
return M::default_m; // some static M to indicate 'missing', or maybe you throw
}();
Хорошая идея или слишком умен, чтобы пройти проверку кода? Каким был бы идиоматический способ сделать это в современном C++?