std :: async не создаст новый поток, если возвращаемое значение не сохранено - PullRequest
13 голосов
/ 29 февраля 2012

Считайте, что у меня есть ламба foo, которая просто что-то делает и не должна ничего возвращать. Когда я делаю это:

std::future<T> handle = std::async(std::launch::async, foo, arg1, arg2);

Все работает нормально, и ламба будет порождена в новом потоке. Однако, когда я не сохраняю std::future, который возвращает std::async, foo запускается в главном потоке и блокирует его.

std::async(std::launch::async, foo, arg1, arg2);

Что мне здесь не хватает?

Ответы [ 3 ]

17 голосов
/ 29 февраля 2012

Из just::thread документации :

Если для политики установлено значение std::launch::async, то INVOKE(fff,xyz...) запускается в своем собственном потоке. Возвращенный std::future станет готовым, когда этот поток завершится, и будет содержать либо возвращаемое значение, либо исключение, вызванное вызовом функции. Деструктор последнего объекта будущего, связанный с асинхронным состоянием возвращенного std::future, должен блокироваться, пока будущее не будет готово.

В

std::async(std::launch::async, foo, arg1, arg2);

Возвращенное будущее нигде не назначено, и его деструкторы блокируются до тех пор, пока не закончится foo.

4 голосов
/ 10 октября 2012

Я хотел бы добавить ссылку на статью Херба Саттера о async и ~ future , в которой он утверждает, что фьючерсы никогда не должны блокироваться.

0 голосов
/ 19 января 2017

Почему блокировка?

  1. std::async(); возвращает std::future временный объект
  2. временный объект немедленно уничтожается, вызывая desctructor.
  3. std::future деструктор блокирует. Это плохо и хлопотно.

Почему присвоение в порядке?

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

Пример кода: main1 в порядке. main2 и main3 эквивалентно блокируют основной поток.

void forever() {
    while (true);
}

void main1() {
    std::future<void> p = std::async(std::launch::async, forever);
    std::cout << "printing" << std::endl; // can print, then forever blocking
}

void main2() {
    std::async(std::launch::async, forever);
    std::cout << "printing" << std::endl; // forever blocking first, cannot print
}

void main3() {
    {std::future<void> p = std::async(std::launch::async, forever);}
    std::cout << "printing" << std::endl; // forever blocking first, cannot print
}

Взгляните на cplusplus.com

Возвращаемое значение std :: async Когда выбрано launch :: async, возвращаемое будущее связывается с конец созданного потока, даже если к его общему состоянию никогда не обращаются: в этом случае его деструктор синхронизируется с возвращением fn. Следовательно, возвращаемое значение не должно игнорироваться для асинхронного поведение, даже когда fn возвращает void.

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