当std :: future准备好被检索时发信号通知主线程

bpe*_*kes 10 c++ asynchronous future

我想了解的std::async,std::future系统的.我不太明白的是你如何处理运行多个异步"任务",然后,基于返回第一个,第二个等,运行一些额外的代码.

示例:假设您的主线程处于一个简单的循环中.现在,根据用户输入,您可以通过运行多个功能std::async,并将期货保存在std::list.

我的问题是,如何从std::async可以指定哪个未来完成的函数中传回信息?

我的主要线程基本上是在消息循环中,我需要做的是通过std::async能够以某种方式指定哪个未来完成的消息的队列来运行.问题是该功能无法访问未来.

我只是错过了一些东西吗?

这是我想要完成的一些伪代码; 额外的积分,如果有办法有办法让一个方法来使用取消令牌"取消"请求.

class RequestA
{
public:
    int input1;

    int output1;
};

main()
{
    while(1)
    {
       //check for completion
       // i.e. pop next "message"
       if(auto *completed_task = get_next_completed_task())
       {
          completed_task->run_continuation();
       }

       // other code to handle user input
       if(userSaidRunA())
       {
          // note that I don't want to use a raw pointer but
          // am not sure how to use future for this
          RequestA *a = new RequestA();
          run(a, OnRequestTypeAComplete);
       }

    }
}

void OnRequestTypeAComplete(RequestA &req)
{
    // Do stuff with req, want access to inputs and output
}
Run Code Online (Sandbox Code Playgroud)

Gal*_*lik 2

您可以创建一个struct包含标志并将对该标志的引用传递给您的线程函数。

有点像这样:

int stuff(std::atomic_bool& complete, std::size_t id)
{
    std::cout << "starting: " << id << '\n';

    // do stuff
    std::this_thread::sleep_for(std::chrono::milliseconds(hol::random_number(3000)));

    // generate value
    int value = hol::random_number(30);

    // signal end
    complete = true;
    std::cout << "ended: " << id << " -> " << value << '\n';

    return value;
}

struct task
{
    std::future<int> fut;
    std::atomic_bool complete;

    task() = default;
    task(task&& t): fut(std::move(t.fut)), complete(t.complete.load()) {}
};

int main()
{
    // list of tasks
    std::vector<task> tasks;

    // reserve enough spaces so that nothing gets reallocated
    // as that would invalidate the references to the atomic_bools
    // needed to signal the end of a thread
    tasks.reserve(3);

    // create a new task
    tasks.emplace_back();

    // start it running
    tasks.back().fut = std::async(std::launch::async, stuff, std::ref(tasks.back().complete), tasks.size());

    tasks.emplace_back();
    tasks.back().fut = std::async(std::launch::async, stuff, std::ref(tasks.back().complete), tasks.size());

    tasks.emplace_back();
    tasks.back().fut = std::async(std::launch::async, stuff, std::ref(tasks.back().complete), tasks.size());

    // Keep going as long as any of the tasks is incomplete
    while(std::any_of(std::begin(tasks), std::end(tasks),
        [](auto& t){ return !t.complete.load(); }))
    {

        // do some parallel stuff
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }

    // process the results

    int sum = 0;
    for(auto&& t: tasks)
        sum += t.fut.get();

    std::cout << "sum: " << sum << '\n';
}
Run Code Online (Sandbox Code Playgroud)