В приведенном ниже примере, если мы игнорируем мьютекс в течение секунды, копия elision может исключить два вызова конструктора копирования.
user_type foo()
{
unique_lock lock( global_mutex );
return user_type(...);
}
user_type result = foo();
Теперь в правилах исключения копирования не упоминается многопоточность, но мне интересно, должно ли это на самом деле происходить через такие границы. В описанной выше ситуации, после освобождения мьютекса, происходит окончательное копирование в потоке логической абстрактной машины. Однако, если копии опущены, структура данных результата инициализируется в мьютексе, таким образом, это происходит между потоками до освобождения мьютекса.
Мне еще предстоит подумать о конкретном примере того, как исключение копирования может действительно привести к состоянию гонки, но вмешательство в последовательность памяти может показаться проблемой. Кто-нибудь может однозначно сказать, что это не может вызвать проблемы, или кто-то может привести пример, который действительно может сломаться?
Чтобы убедиться, что ответ не относится только к особому случаю, обратите внимание, что разрешение на копирование (согласно моим прочтениям) все еще разрешено, если у меня есть утверждение типа new (&result)( foo() )
. То есть result
не обязательно должен быть стековым объектом. user_type
сам может также работать с данными, разделяемыми между потоками.
Ответ : Я выбрал первый ответ как наиболее актуальное обсуждение. По сути, поскольку стандарт гласит, что исключение может произойти, программист должен быть осторожным, когда это происходит за пределами синхронизации. Нет указаний на то, является ли это преднамеренным или случайным требованием. Нам по-прежнему не хватает ни одного примера, показывающего, что может пойти не так, поэтому, возможно, это не проблема в любом случае.