所以我的用例如下:我在命名空间中定义了一些函数和字段。其中一个函数将初始化字段,然后在调用std :: async中运行另一个函数。被调用的函数应该无限期地运行,直到被标记为停止,最常见的是从它自己的线程之外。基本代码看起来像这样
namespace Game
{
void Create() {
Initialize();
auto returned = std::async(RunGameLoop, std::ref(FLAGS));
}
}
现在,我尝试实现这一点的方法是在命名空间中初始化这些标志:
namespace Game
{
namespace // This is used because the fields and functions here should be for internal use only
{
bool stopped = false;
}
}
在RunGameLoop函数内部,基本结构设置如下
namespace Game
{
namespace // This is used because the fields and functions here should be for internal use only
{
void RunGameLoop()
{
while (!stopped)
{
// ... do stuff
}
}
}
}
但似乎由于异步如何工作,如果我从RunGameLoop函数内部以外的任何地方更改stopped
的值,则RunGameLoop函数看不到任何更改。据推测,在创建异步函数调用时,C ++只是在构造时复制范围内的所有值,并通过值而不是引用传递它们。
我的问题是:如何在异步函数循环中使这个变化明显?甚至更好:有没有更好的方法来通过C ++中的异步函数来传递这样的简单全局标志?我已经尝试过使用std :: ref,传递指针,并通过引用传递整个标志映射,但是看起来RunGameLoop函数之外的任何更改都不会在RunGameLoop函数中显而易见。
编辑:我设法以最小的例子复制了这个问题,这个程序将无限期地运行,并且确实永远不会违反第二个std :: cout语句。实际上,std :: async调用似乎根本不是异步运行函数,这比我在我自己的项目中经历的要严格得多。我承认我可能误解了应该如何使用std :: async,但似乎这段代码对我有用。
编辑2:我搞砸了我之前的例子,所以我修复了它。不幸的是现在它似乎表现得像预期的那样,不像我的实际项目:
#include <iostream>
#include <future>
namespace test
{
namespace
{
std::atomic<bool> testbool = false;
std::future<void> returned;
void queryTestBool()
{
while (!testbool)
{
}
std::cout << "EXITED THREAD: " << std::boolalpha << testbool << std::endl;
}
}
void Initialize()
{
testbool = false;
}
void Delete()
{
testbool = !testbool;
returned.get();
}
void Create()
{
Initialize();
returned = std::async(queryTestBool);
}
}
int main()
{
using namespace test;
std::cout << std::boolalpha << testbool << std::endl;
Create();
Delete();
std::cout << std::boolalpha << testbool << std::endl;
}
该程序输出
false
EXITED THREAD: true
true
意味着Delete函数不仅成功地更改了testbool
的值,而且在异步while循环中注意到了这种变化。最后一部分是由于某种原因在我自己的项目中发生的事情,即使我使用std :: atomic。我会进一步调查。
答案 0 :(得分:0)
所以我感到非常愚蠢。经过几周的挣扎,实现了各种各样的东西,我终于发现我的测试叫做Delete()函数的地方被跳过了,因为断言失败,我没想到在运行其余部分之前让测试退出......神秘解决了