Замена std::async собственной версией, но где должен работать std::promise?

Я использую vc2011, и получается std::async(std::launch::async,.., )немного глючит (иногда он не создает новые потоки и запускает их параллельно, а вместо этого повторно использует потоки и запускает задачи один за другим). Это слишком медленно, когда я делаю дорогие сетевые звонки. Поэтому я решил написать свою собственную асинхронную функцию. Однако я застрял, где должен жить std::promise? В функции потока 1), асинхронной функции 2)или вызывающей функции 3).

Код:

#include 
#include 
#include 
#include 
#include 

std::string thFun() {
    throw std::exception("bang!");
    return "val";
}

std::future myasync(std::promise& prms) {
//std::future myasync() {
    //std::promise prms; //needs to outlive thread. How?

    std::future fut = prms.get_future();
    std::thread th([&](){
        //std::promise prms; //need to return a future before...
        try {
            std::string val = thFun();

            prms.set_value(val);

        } catch(...) {
            prms.set_exception(std::current_exception());
        }

     });

    th.detach();
    return fut;
}

 int main() {

    std::promise prms; //I really want the promise hidden iway in the myasync func and not live here in caller code but the promise needs to outlive myasync and live as long as the thread. How do I do this?
    auto fut = myasync(prms);

    //auto fut = myasync(); //Exception: future already retrieved

    try {
        auto res = fut.get();
        std::cout << "Result: " << res << std::endl;

    } catch(const std::exception& exc) {
        std::cout << "Exception: " << exc.what() << std::endl;
    }

 }

Кажется, я не могу пройти мимо того факта, что std::обещание должно пережить асинхронную функцию (и жить так же долго, как поток), поэтому обещание не может жить как локальное переменная в асинхронной функции. Но std::promise также не должен жить в коде вызывающей стороны, поскольку вызывающей стороне нужно знать только о фьючерсах. И я не знаю, как заставить обещание жить в функции потока, поскольку асинхронный вызов должен вернуть будущее, прежде чем он даже вызовет функцию потока. Я ломаю голову над этим.

У кого-нибудь есть идеи?

Редактировать:Я подчеркиваю это здесь, так как верхний комментарий немного дезинформирован. Хотя по умолчанию для std::asycn разрешено использовать отложенный режим, когда политика запуска std::launch::async задана явно, он должен вести себя так, как если бы потоки порождались и запускались одновременно (см. формулировку на en.cppreference.com/w/cpp/thread/async). См. пример на pastebin.com/5dWCjjNY для одного случая, когда поведение отличается от vs20011. Решение отлично работает и ускорило мое приложение в реальном мире в 10 раз.

Редактировать 2:MS исправила ошибку.Подробнее здесь:https://connect.microsoft.com/VisualStudio/feedback/details/735731/std-async-std-launch-async-does-not-behave-as-std-thread

11
задан petke 30 April 2012 в 00:13
поделиться