передать значение в основной поток из дочернего потока, используя обещание и будущее - PullRequest
0 голосов
/ 14 декабря 2018

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

#include <bits/stdc++.h>
using namespace std;
int sampleFunc(vector<future<int>> &f) {

    int a = f[0].get();
    cout <<"got a from promise 1" << endl;

    int b = f[1].get();
    cout <<"got b from promise 2" << endl;

    return a + b;
}
int main() {
    int outputVal;
    int k = 2;
    std::vector<promise<int>> p(k);
    vector<future<int>> f(k);

    f[0] = p[0].get_future();
    f[1] = p[1].get_future();

    std::future<int> fu = std::async(std::launch::async,sampleFunc,std::ref(f));

    std::this_thread::sleep_for(chrono::milliseconds(1000));

    p[0].set_value(2);

    std::this_thread::sleep_for(chrono::milliseconds(3000));

    p[1].set_value(4);

    outputVal = fu.get();

    cout << outputVal << endl;
}

Задержки могут иметь другое значение, например, значения a и b могут быть еще не готовы (возможно, мы ожидаем, что какая-то другая задачаслучиться внутри основного потока).

Что, как говорится, как передать частичные данные (асинхронно, как в примере выше) из дочернего потока в основной поток?Можно ли распространить эту модель передачи данных на другие потоки (дочерний поток на другой дочерний поток)?

Спасибо!

1 Ответ

0 голосов
/ 17 декабря 2018

Вы можете использовать «классическое решение» для обмена данными между потоками: shared_ptr.Я не думаю, что promise и future могут (обычно) использоваться для передачи частичных данных: «Обратите внимание, что объект std :: обещание предназначен для использования только один раз».(cppreference.com: здесь ).Я изменил ваш код (немного), чтобы показать мою точку зрения, пожалуйста, возвращайтесь, если есть проблемы:

#include "bits/stdc++.h"
using namespace std;

//  only a string, but a structure is more general
struct Transfer {
    std::string m_status;

    Transfer() noexcept {};
    Transfer(const std::string& status) : m_status(status)
    {};
};

// std::atomic_shared_ptr is a (new) alternative to this use of std::shared_ptr

//  warning: atomic functions for shared pointers do work on the shared 
//      pointer, not on the contained data 
int sampleFunc(vector<future<int>> &f, std::shared_ptr<Transfer>& status) {

    std::atomic_store(&status, std::make_shared<Transfer>("Waiting for the first result ..."));

    int a = f[0].get();

    std::this_thread::sleep_for(chrono::milliseconds(100)); // to "sync" the output
    cout << "got a from promise 1" << endl;

    std::atomic_store(&status, std::make_shared<Transfer>("Waiting for the second result ..."));

    int b = f[1].get();

    std::this_thread::sleep_for(chrono::milliseconds(100));  //to "sync" the output
    cout << "got b from promise 2" << endl;

    std::atomic_store(&status, std::make_shared<Transfer>("Finishing ..."));

    std::this_thread::sleep_for(chrono::seconds(1));

    return a + b;
}

int main() {
    int outputVal;
    int k = 2;
    std::vector<promise<int>> p(k);
    vector<future<int>> f(k);

    f[0] = p[0].get_future();
    f[1] = p[1].get_future();

    std::shared_ptr<Transfer> status_shared = std::make_shared<Transfer>("Started");
    //  do not forget to use std::ref
    std::future<int> fu = std::async(std::launch::async, sampleFunc, std::ref(f), std::ref(status_shared));

    const auto wait_for_1 = std::async(std::launch::async, [](promise<int>& p) {
        std::this_thread::sleep_for(chrono::milliseconds(1000));
        p.set_value(2);
    }, std::ref(p[0]));

    const auto wait_for_2 = std::async(std::launch::async, [](promise<int>& p) {
        std::this_thread::sleep_for(chrono::milliseconds(3000));
        p.set_value(4);
    }, std::ref(p[1]));

    do {
        const auto status = std::atomic_load(&status_shared);
        cout << status->m_status << '\n';
    } while (future_status::timeout == fu.wait_for(chrono::seconds(1)));

    outputVal = fu.get();

    cout << outputVal << endl;

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...