C ++从std :: async函数读取命名空间中的全局变量标志

时间:2018-06-03 11:10:53

标签: c++

所以我的用例如下:我在命名空间中定义了一些函数和字段。其中一个函数将初始化字段,然后在调用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。我会进一步调查。

1 个答案:

答案 0 :(得分:0)

所以我感到非常愚蠢。经过几周的挣扎,实现了各种各样的东西,我终于发现我的测试叫做Delete()函数的地方被跳过了,因为断言失败,我没想到在运行其余部分之前让测试退出......神秘解决了