我遇到了由std :: async啓動的進程的一些問題。C + + std ::異步調用類成員方法不會看到變量更改
class BaseClass {
public:
BaseClass() {enabledFlag = false;}
virtual ~BaseClass() {}
protected:
int process();
bool enabledFlag;
};
int BaseClass::process() {
int rc = -1;
if (enabledFlag == false) {
std::cout << "Not enabled\n" << std::flush;
return rc;
}
rc = 0;
while (enabledFlag) {
// this loop should set rc to be something other than zero if an error is to be signalled
// otherwise loop here doing stuff until the user sets enabledFlag=false
}
return rc;
}
class DerivedClassWithExposedMembersForTesting : public BaseClass {
public:
using BaseClass::enabledFlag;
using BaseClass::process;
};
在我的谷歌測試測試:
TEST(FixtureName, process_exitsWithRC0_WhenEnabledFlagSetTrueDuringExecution {
DerivedClassWithExposedMembersForTesting testClass;
testClass.enabledFlag = true;
// print status
std::cout << "Enabled: " << testClass.enabledFlag << std::endl << std::flush;
std::future<int> returnCodeFuture = std::async(std::launch::async, &DerivedClassWithExposedMembersForTesting::process, &testClass); // starts background execution
// set flag to false to kill loop
testClass.enabledFlag = false;
int rc = returnCodeFuture.get();
EXPECT_EQ(0, rc);
}
我的std ::異步的理解是,它訂於不久後運行調用異步和執行的主線程將阻塞如果線程尚未完成,則在get()調用。對get()的調用將返回process()的返回值。
如果testClass未啓用,process()被設置爲不運行,因此我在測試中啓用它。
我希望看到:
Enabled: 1
// test passes
我看到的是:
Enabled: 1
Not enabled
// test fails
Failure
Value of: rc
Actual: -1
Expected: 0
爲什麼過程的std ::觸發異步沒有看到由主設定的enabledFlag的價值進行異步調用之前的進程?
注:enabledFlag應該從外部過程中設置,一般不從內環路,因此這種結構
** **更新 按我的意見,我通過將它固定以下行測試,只是後調用異步():
// Use wait_for() with zero milliseconds to check thread status; delay until it has started
while (returnCodeFuture.wait_for(std::chrono::milliseconds(0)) == std::future_status::deferred) {}
不要使用非'原子'進行線程間通信。 – 2014-09-12 13:02:29
對不起,@JoachimPileborg,在複製代碼時發生錯誤。現在修復。 – John 2014-09-12 13:06:53
兩個線程可能同時訪問'testClass.enabledFlag',其中一個線程修改它。這是*數據競爭*的定義; C++沒有定義數據競爭程序的行爲。您必須使用互斥鎖或將其聲明爲原子(即,std :: atomic')來同步對'testClass.enabledFlag'的訪問。 –
Casey
2014-09-12 19:07:49