форсирование: асинхронно ждать будущего завершения - PullRequest
0 голосов
/ 13 февраля 2019

Вот моя проблема, скажем, у меня есть кусок кода синхронизации, который должен выполняться синхронно, и у меня есть пул потоков для этого.Я могу предоставить выноску для этой «задачи», которая может установить значение для обещания повышения.

Теперь я жду, пока один поток диспетчера запустится как io_service, этот сервис получит «запрос» через io.post, выберет рабочий поток из пула, отправит ему задание и передаст «выноску»(это будет работать на рабочем потоке и "делать" обещание. set_value ". То, что я хочу сделать, это какое-то" продолжение ", которое будет выполняться на" io_service ". Один из способов, которым я могу это сделать, - это" вызов "представит «новое задание» на io_service, это задание может быть лямбда, переданным из «инициатора запроса», следовательно, не используя «обещание» и «будущее». Вопрос в том, могу ли я как-то использовать «будущее» для этого?заставить "promise.set_value" передать это "продолжение".

Я попробовал следующий код, как предложено ниже:

 void worker(promise<int>& p) {
  sleep(10);
  p.set_value(10);
}


int main(int argc, char **argv) {
    io_service io;
    io_service::work work(io);
    promise<int> p;
    io.post([&] {
        std::cout << "submission id:" << boost::this_thread::get_id() << std::endl;
        boost::thread my_thread(&worker, boost::ref(p));
        p.get_future().then(launch::async, [](future<int> p){
            std::cout << "completion thread id:" << boost::this_thread::get_id() << std::endl;
        });
    });
    io.run();
}

вот вывод: идентификатор задания: 7f0c7b825b80 идентификатор завершения задания: 7f0c798be700

Кажется, что он выполняет завершение в другом потоке, и мне нужно, чтобы он вызывался на "io_service" one ... Должен ли я просто "опубликовать" из стороннего потока новый "JOB"?

Я используюхотя повышение 1.65.

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

По сути, вы хотите синхронно post дополнительный код, когда функция предоставляет результат.Использование promise для синхронной связи является излишним (помните, что promise использует объект синхронизации).

Ваша первоначальная мысль post продолжить обратно к io_service, минуя promise,это лучшая идея:

int worker() {
    this_thread::sleep_for(2s);
    return 10;
}

int main(int argc, char **argv) {
    io_service io;
    io_service::work work(io);
    thread my_thread; // assuming this represents the thread pool
    io.post([&] {
        std::cout << "submission id:" << this_thread::get_id() << std::endl;
        my_thread = thread([&io] { // assuming this represents posting a task to the pool
            auto result = worker();
            io.post([&io, result] {
                std::cout << "completion thread id:" << this_thread::get_id()
                          << ", result:" << result << std::endl;
            });
        });
    });
    io.run();
}

Примечание.Идея в другом ответе такова:

    p.get_future().then(io.get_executor(), [](future<int> p) {
        std::cout << "completion thread id:" << boost::this_thread::get_id() << std::endl;
    });

Он не будет работать для вас, потому что io_context::executor_type и future.then([Executor&],...) доступны из Boost 1.66 (возможно, все еще не будут работать из-за отсутствия try_executing_one() в исполнителе ASIO).

0 голосов
/ 13 февраля 2019

Возможно, вы захотите взглянуть на boost.future:

https://www.boost.org/doc/libs/1_69_0/doc/html/thread/synchronization.html#thread.synchronization.futures.then

boost::future превосходит std::future, поскольку вы можете прикрепить продолжение к будущему с помощью.then([executor], continuation_function).

В последних версиях asio io_context::executor_type (из .get_executor()) и io_context::strand моделируют исполнителя.

...