2014-11-17 17 views
7

Sto lavorando a un programma in cui mi piacerebbe utilizzare async in un ciclo. Nel codice di esempio che ho incluso ci sono solo 10 elementi, quindi ho potuto creare facilmente una variabile esplicita per ogni elemento. Tuttavia, nel mio programma principale, il numero di elementi nel vettore può variare. Idealmente, mi piacerebbe creare un vettore di thread asincroni - uno per ogni elemento dell'array - che vengono rimandati sul vettore asincrono mentre faccio il ciclo. Quindi voglio aspettare che tutti si completino, e poi usare " get() "per restituire tutte le loro uscite.Numero variabile di thread asincroni con C++ 11

Il codice seguente chiamerà asincrono assegnando una variabile esplicita per ogni thread, ma qualcuno sa come chiamare in modo dinamico asincrono in un vettore senza dover assegnare esplicitamente una variabile ad esso? Idealmente, mi piacerebbe che questo programma chiamasse "std :: cout" una volta ogni volta che passava in loop, invece che una sola volta.

#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

E quale è esattamente la tua domanda? – Columbo

+0

Come chiamare in modo dinamico asincrono ogni volta che passa il ciclo anziché dover creare una variabile in modo esplicito. –

+0

Il codice sopra riportato ha un grave difetto, ogni volta che assegni un nuovo futuro a 'a' lo imponi di bloccare e attendi che il thread associato al suo vecchio valore finisca, quindi stai funzionando in modo efficace in serie. Ad ogni modo, sono sorpreso che la soluzione a un numero dinamico di futuri non sia del tutto ovvia: immagazzina ogni nuovo futuro in un contenitore di dimensioni dinamiche, come un vettore. Hai persino detto tu stesso: _ "Mi piacerebbe creare un vettore di thread asincroni, uno per ogni elemento dell'array, che viene spostato sul vettore asincrono mentre faccio il loop." _ Quindi perché non hai appena Fai quello! –

risposta

7

Una risposta tra cui 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

Se ho capito bene, potrebbe essere qualcosa di simile:

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); 
} 

Mi dispiace non posso postare come un commento, ma in questo modo, a seconda della logica, e se funziona, allora si dovrebbe essere in grado di manipolare dinamicamente il vettore vessel.


Aggiornamento

meglio ancora:

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

in questo modo non è necessario dichiarare in modo esplicito una variabile. Ma si dovrà delete volta che hai finito:

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

Dovresti usare 'std :: unique_ptr' per gestire la memoria. – 0x499602D2

+0

In [CPlusPlus unique_ptr reference] (http://www.cplusplus.com/reference/memory/unique_ptr/), si afferma che gli oggetti 'unique_ptr eliminano automaticamente l'oggetto che gestiscono (usando un deleter) non appena sono essi stessi destroyed'. Grazie per averlo indicato @ 0x499602D2. Questo [esempio] (http://www.cplusplus.com/reference/memory/unique_ptr/get/) illustra come deve essere usato. – GChamon

+3

Meglio non usare puntatori grezzi (eccezione-sicurezza), ancora meglio: non usare affatto i puntatori. Come la risposta di Galiks mostra, è perfettamente ragionevole non usarli. Ridurre l'indirezione è una buona idea (anche se il costo è probabilmente trascurabile qui). – stefan

12

si può risolvere questo con la creazione di un vettore di futures per abbinare il vostro discussioni vettore, qualcosa di simile a questo:

#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'; 
} 

noti l'uso di std::cref per passare const riferimento. Utilizzare std::ref per passare riferimenti non cost.

+2

+1 per idiomatic C++ 11 –

+0

'for (auto && f: futures)' questo è qualcosa che DEVO apprendere – GChamon

+2

Controllo ['std :: future :: valid'] (http://en.cppreference.com/w/cpp/thread/future/ valido) è estraneo qui, restituirà sempre vero. – Casey

Problemi correlati