如何从std :: vector自动删除完成的期货

时间:2017-07-15 11:05:46

标签: c++ c++11 vector

在下面的示例中,mEventExecutors是std::vector<std::future<void>>。我希望能够在矢量完成后从矢量中删除期货。可以这样做吗?

void RaiseEvent(EventID messageID)
{
    mEventExecutors.push_back(std::move(std::async([=]{
            auto eventObject = mEventListeners.find(messageID);
            if (eventObject != mEventListeners.end())
            {
                for (auto listener : eventObject->second)
                {
                    listener();
                }
            }
        })
    ));
}

2 个答案:

答案 0 :(得分:1)

在我看来,不要使用std::async是一个简单的解决方案,而是使用std::thread

你需要小心,你的代码目前有很多数据竞争。考虑使用另一种互斥或其他技术来防止它们。

std::thread{[=]() {
    // Task is running...
    auto eventObject = mEventListeners.find(messageID);
    if (eventObject != mEventListeners.end())
    {
        for (auto listener : eventObject->second)
        {
            listener();
        }
    }
}.detach(); // detach thread so that it continues

答案 1 :(得分:1)

这个问题本身已经被另一个人回答了,但它激起了我对如何在最少的代码行中实现一个功能齐全,线程安全的任务管理器的好奇心。

我也想知道是否有可能将任务等待作为期货,或者可选择提供回调函数。

当然,这提出了一个问题:这些未来是否可以使用INSERT INTO `googlemaps_marker` (`descr`, `Lat`, `Lng`, `pretty_url`, `ID`, `zone_ID`, `kind`, `author_id`, `author`, `date_updated`) VALUES ('sasasasdas', '41.27780646738183', '-7.437744140625', 'sasasasdas', 4, 4, 1, '1', 'Admini Istrator', '2017-07-15 18:20:40') 的性感延续语法,而不是阻止代码。

这是我的尝试。

.then(xxx)的作者克里斯托弗科尔霍夫赞不绝口。通过研究他那令人敬畏的工作,我学会了将课程分成以下内容的价值:

  • handle - 控制对象的生命周期
  • service - 提供对象逻辑,在对象impls之间共享的状态,并管理实现对象的生命周期,如果它们比句柄更长(通常依赖于回调的任何东西),并且
  • 实现提供了每个对象的状态。

所以这是一个调用代码的例子:

boost::asio

这会产生以下输出:

int main() {
    task_manager mgr;

    // an example of using async callbacks to indicate completion and error
    mgr.submit([] {
                   emit("task 1 is doing something");
                   std::this_thread::sleep_for(1s);
                   emit("task 1 done");
               },
               [](auto err) {
                   if (not err) {
                       emit("task 1 completed");
                   } else {
                       emit("task 1 failed");
                   }
               });

    // an example of returning a future (see later)
    auto f = mgr.submit([] {
        emit("task 2 doing something");
        std::this_thread::sleep_for(1500ms);
        emit("task 2 is going to throw");
        throw std::runtime_error("here is an error");
    }, use_future);

    // an example of returning a future and then immediately using its continuation.
    // note that the continuation happens on the task_manager's thread pool
    mgr.submit([]
               {
                   emit("task 3 doing something");
                   std::this_thread::sleep_for(500ms);
                   emit("task 3 is done");
               },
               use_future)
            .then([](auto f) {
                try {
                    f.get();
                }
                catch(std::exception const& e) {
                    emit("task 3 threw an exception: ", e.what());
                }
            });

    // block on the future of the second example
    try {
        f.get();
    }
    catch (std::exception &e) {
        emit("task 2 threw: ", e.what());
    }
}

这里是完整的代码(在苹果clang上测试,比gcc更加混乱,所以如果我错过了这个 - &gt;在lambda中,我的道歉):

task 1 is doing something
task 2 doing something
task 3 doing something
task 3 is done
task 1 done
task 1 completed
task 2 is going to throw
task 2 threw: here is an error