Можно ли безопасно перемещать unique_ptr с атомарными операциями c ++ 11?
В настоящее время у меня есть такой код
std::unique_ptr<SyncToken> DataManager::borrowSyncToken()
{
std::unique_lock<std::mutex> syncTokenLock(syncTokenMutex);
return std::move(syncToken);
}
Мне интересно, есть ли более элегантный способ, например, просто объявить:
std::atomic<std::unique_ptr<SyncToken>> syncToken;
и избегая необходимости мьютекса. Или, возможно, мне вообще не нужно заботиться о блокировке, а std :: move уже атомарен?
После проведенных исследований мне кажется:
Нет, это невозможно.
Значение T
который вы передаете std::atomic
должно быть тривиально копируемым, что std::unique_ptr
не является. Операции как std::atomic::load
или же std::atomic::store
взять T объектов по значению.
Упаковка чего-либо в std::atomic
также не выполняет операции из значения Atomic.
Когда используешь std::unique_ptr
в атомарном контексте вы должны подумать о том, что у вас могут возникнуть проблемы с управлением ресурсами. Вы никогда не знаете, сколько потоков все еще ссылаются на ваши данные, эту проблему можно решить с помощью std::shared_ptr
который использует атомный подсчет ссылок. (Вы должны проверить, действительно ли это атомно, используя std::atomic_is_lock_free
функция. )
Одна вещь, на которую я также наткнулся при просмотре вашего кода, — это намерение borrowSyncToken
функция. Это называется одолжить, но вы передаете право собственности на токен вызывающей стороне, выдвигая std::unique_ptr
как передается право собственности и что получают другие потоки, когда DataManager в настоящее время не владеет токеном?
Других решений пока нет …