2015-01-26 2 views
1

Интересно, если этот код нормально или нет:Правильно ли этот код правильно синхронизирован?

#include <iostream> 
#include <future> 
struct Foo 
{ 
    Foo() 
     :m_a(0) 
    { 
    } 

    int m_a; 
}; 

int main() 
{ 
    Foo f; 
    auto handle = 
     std::async(std::launch::async, 
       [](Foo* f) { std::cout << f->m_a << '\n'; } , 
       &f 
      ); 

    handle.get(); 
} 

Я считаю, что m_a должен быть защищен с помощью механизма синхронизации, но мой коллега говорит, что это не нужно.

EDIT: Для того, чтобы прояснить мой вопрос: Я обеспокоен тем, что операция STORE из конструктора Foo() происходит после операции загрузки из другого потока. Я не вижу, какой механизм мешает компилятору выполнить эту инструкцию в этом порядке.

EDIT: Я считаю, что с энтузиазмом компилятор мог бы решить встраивать конструктор, и задержать операцию STORE для после операции ВЫЗОВА к std::async. В этом случае второй поток мог бы получить доступ к m_a, прежде чем он будет передан в память.

+2

Ничто другое не пишет в 'f' или не читает его в' main', поэтому синхронизация не синхронизируется. Но это поможет, если вы перечислите некоторые аргументы с каждой стороны. – juanchopanza

+0

@juanchopanza В 'f' есть что-то другое: оно разрушается автоматически, то есть доступ к' f-> m_a' лучше не произойдет после уничтожения 'f'. –

+0

@FrerichRaabe Он уничтожается после вызова 'handle.get()'. Поэтому я имел в виду, что в 'main()' read-write нет, пока выполняется асинхронная операция. Теперь это было небезопасно, 'std :: async' было бы чертовски бесполезно. – juanchopanza

ответ

1

Да, это правильно синхронизировано.

Из спецификации async C++ 11 30.6.8/5:

призывание async синхронизируется с вызовом f.

где f является функция аргумента async (лямбда в вашем примере).

Инициализация f.m_a секвенирована до вызова async и, следовательно, перед любым доступом с помощью асинхронной функции.

Кроме того,

завершение функции F секвенируют до общего состояния производится готов.

, так что доступ должен произойти до того, как будет вызван вызов get(), и, следовательно, перед тем, как объект будет уничтожен.

+0

Меня больше беспокоит доступ к 'm_a' внутри лямбда-функции в другом потоке. Какие гарантии, что операция STORE завершена? – qdii

+0

@qdii: Извините, я неправильно понял вопрос. Мой ответ не отвечает. –

+0

@qdii: Это должно ответить на вопрос сейчас. Извините за путаницу. –

Смежные вопросы