2014-11-17 8 views
7

Pracuję nad programem, w którym chciałbym użyć asynchronizacji w pętli. W przykładowym kodzie, który zawarłem, jest tylko 10 elementów, więc mogłem z łatwością stworzyć wyraźną zmienną dla każdego elementu. Jednak w moim głównym programie liczba elementów w wektorze może być różna. Idealnie chciałbym stworzyć wektor asynchronicznych wątków - po jednym dla każdego elementu w tablicy - które są wypychane z powrotem na wektor asynchroniczny, kiedy przechodzę przez pętlę. Następnie chcę poczekać na zakończenie wszystkich, a następnie użyć " get() ", aby zwrócić wszystkie swoje wyjścia.Zmienna liczba asynchronicznych wątków z C++ 11

Poniższy kod wywoła async, przypisując jawną zmienną dla każdego wątku, ale czy ktoś wie jak dynamicznie wywoływać asynchroniczne w wektorze bez konieczności jednoznacznego przypisania do niego zmiennej? Idealnie, chciałbym, aby ten program wywoływał "std :: cout" raz za każdym razem, gdy przechodził, zamiast tylko raz.

#include <iostream> 
#include <vector> 
#include <string> 
#include <future> 

std::string hi (std::string input) 
{ 
    return "hello, this is " + input; 
} 

int main() 
{ 
    std::vector<std::string> test_vector(10, "a test"); 
    std::future<std::string> a; 
    std::future<std::string> b; 

    for (int i = 0; i < test_vector.size (); i++) 
    { 
     a = std::async(std::launch::async, hi, test_vector[i]); 
    } 

    std::cout << a.get() << std::endl; 

    return 0; 
} 
+0

Jakie jest dokładnie twoje pytanie? – Columbo

+0

Jak dynamicznie wywoływać asynchroniczne za każdym razem, gdy przechodzi pętla, zamiast konieczności jawnego tworzenia zmiennej. –

+0

Kod, jak napisano powyżej, ma poważną wadę, za każdym razem, gdy przypisujesz nową przyszłość do 'a', zmuszasz ją do blokowania i czekania na zakończenie wątku związanego z jego starą wartością, dzięki czemu skutecznie działasz w trybie szeregowym. W każdym razie, jestem zaskoczony, że rozwiązanie dynamicznej liczby kontraktów terminowych nie jest całkowicie oczywiste: przechowuj każdą nową przyszłość w dynamicznym pojemniku, takim jak wektor. Sam to powiedziałeś: _ "Chciałbym stworzyć wektor asynchronicznych wątków - po jednym dla każdego elementu w tablicy - które są wepchnięte w wektor asynchroniczny, podczas gdy ja przechodzę przez pętlę." _ Dlaczego nie po prostu Zrób to! –

Odpowiedz

7

Odpowiedź tym std::cout:

std::vector<std::future<std::string>> a; 
for (int i = 0; i < 10; ++i) { 
    a.emplace_back(std::async(hi)); 
} 
for (auto& element : a) { 
    std::cout << element.get() << std::endl; 
} 
3

Jeśli dobrze zrozumiałem, może być coś takiego:

std::vector<std::future<std::string>> vessel; 
for (int i = 0; i < test_vector.size (); i++) 
{ 
    std::future<std::string> aux; 
    aux = std::async(std::launch::async, hi); 
    vessel.push_back(aux); 
} 

Niestety nie mogę zamieścić jako komentarz, ale w ten sposób, w zależności od logiki, a jeśli to działa, to powinno być w stanie dynamicznie manipulować wektorem vessel.


Aktualizacja

jeszcze lepiej:

vessel.push_back(new std::future<std::string>); 
vessel[vessel.size()-1] = std::async(std::launch::async, hi); 

ten sposób nie trzeba jawnie zadeklarować zmienną. Ale trzeba będzie delete po zakończeniu:

for(int i=0; i<(int) vessel.size(); i++) 
{ 
    delete vessel[i]; 
} 
+2

Powinieneś używać 'std :: unique_ptr' do zarządzania pamięcią. – 0x499602D2

+0

W [CPlusPlus unique_ptr reference] (http://www.cplusplus.com/reference/memory/unique_ptr/) podano, że 'unique_ptr objects automatycznie usuwają obiekt, którym zarządzają (za pomocą deletera), gdy tylko sami będą zniszczone ". Dzięki za wskazanie @ 0x499602D2. Ten [przykład] (http://www.cplusplus.com/reference/memory/unique_ptr/get/) ilustruje sposób jego użycia. – GChamon

+3

Lepiej nie używać surowych wskaźników (wyjątek - bezpieczeństwo), jeszcze lepiej: nie używaj w ogóle wskaźników. Jak pokazuje odpowiedź Galiksa, rozsądnie jest nie używać ich. Zredukowanie pośrednictwa jest dobrym pomysłem (chociaż koszty są tu prawdopodobnie pomijalne). – stefan

12

Problem ten można rozwiązać poprzez stworzenie wektor futures pasujące do Twojego wektor wątków, coś takiego:

#include <iostream> 
#include <vector> 
#include <string> 
#include <future> 

std::string hi(const std::string& input) 
{ 
    return "hello, this is " + input; 
} 

int main() 
{ 
    std::vector<std::string> tests = {"one", "two", "three", "four"}; 
    std::vector<std::future<std::string>> futures; 

    // add the futures to the futures vector as you launch 
    // your asynchronous functions 
    for(auto&& t: tests) 
     futures.emplace_back(std::async(std::launch::async, hi, std::cref(t))); 

    // collect your results 
    for(auto&& f: futures) 
     std::cout << f.get() << '\n'; 
} 

Uwaga wykorzystanie std::cref przejść przez const odniesienia. Użyj std::ref, aby przekazać non const reference.

+2

+1 dla idiomatic C++ 11 –

+0

'for (auto && f: futures)' to jest coś, co muszę się nauczyć – GChamon

+2

Sprawdzanie ['std :: future :: valid'] (http://en.cppreference.com/w/cpp/thread/future/ valid) jest tutaj obcy, zawsze zwróci true. – Casey