我正在尝试根据用户输入更改未来对象的行为。
#include <iostream>
#include <future>
//=======================================================================================!
struct DoWork
{
DoWork(int cycles, int restTime) : _cycles(cycles), _restTime(restTime), _stop(false)
{
}
void operator () ()
{
for(int i = 0 ; i < _cycles; ++i)
{
std::this_thread::sleep_for(std::chrono::milliseconds(_restTime));
if(_stop)break;
doTask();
}
}
void stop()
{
_stop = true;
}
private:
void doTask()
{
std::cout << "doing task!" << std::endl;
}
private:
int _cycles;
int _restTime;
bool _stop;
};
//=======================================================================================!
int main()
{
DoWork doObj(50, 500);
std::future<int> f = std::async(std::launch::async, doObj);
std::cout << "Should I stop work ?" << std::endl;
std::cout << "('1' = Yes, '2' = no, 'any other' = maybe)" << std::endl;
int answer;
std::cin >> answer;
if(answer == 1) doObj.stop();
std::cout << f.get() << std::endl;
return 0;
}
//=======================================================================================!
然而,这并不会阻止未来对象的执行。在创建未来对象后,如何更改doObj的行为?
答案 0 :(得分:1)
你有一些问题。首先,您的函数对象实际上不会返回int
,因此std::async
将返回std::future<void>
。您可以通过从int
实际返回DoWork::operator()
,或将async
中的结果存储在std::future<void>
而不是尝试打印来解决此问题。
其次,std::async
复制它的参数,如果它们不在引用包装器中,那么堆栈上的doObj
将不会是正在使用的DoWork
的同一个实例由异步线程。您可以通过在doObj
的参考包装中传递std::async(std::launch::async, std::ref(doObj))
来更正此问题。
第三,主线程和异步线程同时访问DoWork::_stop
。这是数据竞争,意味着程序具有未定义的行为。修复方法是使用_stop
保护对std::mutex
的访问权限,或将其设为std::atomic
。
总而言之,程序应该看起来像(Live at Coliru):
#include <iostream>
#include <future>
//=======================================================================================!
struct DoWork
{
DoWork(int cycles, int restTime) : _cycles(cycles), _restTime(restTime), _stop(false)
{
}
int operator () ()
{
for(int i = 0 ; i < _cycles; ++i)
{
std::this_thread::sleep_for(std::chrono::milliseconds(_restTime));
if(_stop) return 42;
doTask();
}
return 13;
}
void stop()
{
_stop = true;
}
private:
void doTask()
{
std::cout << "doing task!" << std::endl;
}
private:
int _cycles;
int _restTime;
std::atomic<bool> _stop;
};
//=======================================================================================!
int main()
{
DoWork doObj(50, 500);
std::future<int> f = std::async(std::launch::async, std::ref(doObj));
std::cout << "Should I stop work ?" << std::endl;
std::cout << "('1' = Yes, '2' = no, 'any other' = maybe)" << std::endl;
int answer;
std::cin >> answer;
if(answer == 1) doObj.stop();
std::cout << f.get() << std::endl;
}
//=======================================================================================!