Новый std:: shared_timed_mutex позволяет использовать два типа блокировок: общий и эксклюзивный.
Если у вас есть общий замок, есть ли способ его атомарного обмена ( "обновить его" ) до эксклюзивной блокировки? Другими словами, учитывая следующий код, как я могу избежать неатомной капли и повторной блокировки?
std::shared_timed_mutex m; //Guards a std::vector.
m.lock_shared();
//Read from vector. (Shared lock is sufficient.)
// ...
//Now we want to write to the vector. We need an exclusive lock.
m.unlock_shared();
// <---- Problem here: non-atomic!
m.lock();
//Write to vector.
// ...
m.unlock();
В идеале m.unlock_shared(); m.lock();
можно заменить чем-то вроде m.upgrade_to_exclusive();
(или что-то вроде boost::.upgrade_to_unique_lock()
).
В аналогичном вопросе, но для Boost shared_mutex Dave S упоминает
Невозможно преобразовать из общей блокировки в уникальную блокировку или общую блокировку в обновляемую блокировку, не отпуская сначала общую блокировку.
Я не уверен, относится ли это к std:: shared_mutex, хотя я подозреваю, что это так.
Я был бы доволен разумной практикой, основанной на транзакционной памяти std:: atomic/condition_variable или GCC.
Изменить: Ответ Говарда отвечает на мой вопрос. Его предложение N3427 содержит приятные описания механизма для обновления мьютекса. Я по-прежнему приветствую обходы, основанные на транзакционной памяти std:: atomic/condition_variable или GCC.