Тупик при использовании std :: async с будущим в качестве члена - PullRequest
0 голосов
/ 15 октября 2018

Я перенес наше приложение из Objective-C и Cocoa в C ++.В Objective-C я часто использовал Grand Central Dispatch и очень удобные функции dispatch_async.

При переходе на C ++ 11 я нашел std :: async в качестве ближайшего аналога.Я использую его вариант Скотта Мейерса, который гарантирует, что он действительно вызывается асинхронно:

template<typename F, typename... Ts>
inline auto NLA_async(F&& f, Ts&&... params)
{
    return std::async(std::launch::async,
                      std::forward<F>(f),
                      std::forward<Ts>(params)...);
}

Я узнал, что функция на самом деле не будет вызываться асинхронно, если возвращенное будущее не назначено как будущее d 'tor будет ожидать завершения асинхронного блока.

void foo()
{
    NLA_async([]{ // run long task async });
    // future returned from NLA_async not captured 
    // -> std::future d'tor waits for block to be finished
}

Поэтому я подумал, что просто назначу будущее члену класса, чтобы он по крайней мере отправлял асинхронно в большинстве случаев (не идеально, но ядумал быстрый и грязный обходной путь).До сих пор это работало хорошо.

Однако я нахожусь в тупиковой ситуации, которую я пока не понимаю.Похоже, что возможно, что блок выполняется дважды одновременно, что в моем случае вызывает тупик.

Вы можете посмотреть здесь:

http://coliru.stacked - криво.com / a / dc4fcbaff370f1b9

Кто-нибудь может объяснить, почему это выполняется дважды одновременно?

Редактировать: В моем конкретном случае проблема заключается в том, что в конце асинхронногозаблокировать код блокирует мьютекс, выполняет некоторую работу, а затем разблокирует мьютекс.На данный момент мы заходим в тупик.Похоже, что работающий асинхронный блок удаляется до его завершения, так как мьютекс остается заблокированным, хотя и не должен (нет операторов возврата или чего-либо, что могло бы объяснить, почему он не разблокирует мьютекс).

1 Ответ

0 голосов
/ 17 октября 2018

Проблема двух потоков, работающих асинхронно, вероятно, связана с тем, что создание будущего и присвоение его переменной-члену не происходит за один шаг.

Сначала он создается и поток запускается.Затем он присваивается переменной-члену в ожидании завершения первого потока.

Спасибо Бесполезно за указание на это!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...