Sto usando vc2011 e si scopre che std :: async (std :: launch :: async, ...) è un po 'buggato (a volte non genera nuovi thread e li esegue in parallelo, ma riutilizza invece i thread e le attività vengono eseguiti uno dopo l'altro). Questo è troppo lento quando sto facendo chiamate di rete costose. Quindi ho pensato di scrivere la mia funzione asincrona. Mi sto bloccando però, dove dovrebbe std :: promettere live? Nella funzione 1) thread, 2) funzione asincrona o 3) funzione chiamante.Sostituzione di std :: async con la propria versione ma dove dovrebbe std :: promise live?
Codice:
#include <future>
#include <thread>
#include <iostream>
#include <string>
#include <vector>
std::string thFun() {
throw std::exception("bang!");
return "val";
}
std::future<std::string> myasync(std::promise<std::string>& prms) {
//std::future<std::string> myasync() {
//std::promise<std::string> prms; //needs to outlive thread. How?
std::future<std::string> fut = prms.get_future();
std::thread th([&](){
//std::promise<std::string> 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<std::string> 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;
}
}
I cant sembrano andare oltre il fatto che lo std :: promessa ha bisogno di sopravvivere alla funzione asincrona (e vivere più a lungo il filo), quindi la sopraelevazione promessa dal vivo come variabile locale nella funzione asincrona. Ma la std :: promise non dovrebbe vivere anche nel codice del chiamante, poiché il chiamante deve solo conoscere i futures. E non so come rendere la promessa live nella funzione thread in quanto async deve restituire un futuro prima ancora che chiama il thread func. Mi sto grattando la testa su questo.
Qualcuno ha qualche idea?
Edit: sto evidenziando questo qui come il commento principale è un po 'disinformato. Mentre l'impostazione predefinita per std :: asycn è la modalità dererred, quando una politica di avvio di std :: launch :: async è impostata in modo esplicito, deve comportarsi come se "i thread venissero generati ed eseguiti contemporaneamente (vedere wording in it .cppreference.com/w/cpp/thread/asincrona). Vedere l'esempio in pastebin.com/5dWCjjNY per un caso in cui questo non è il comportamento visto in vs20011. La soluzione funziona alla grande e ha velocizzato la mia applicazione del mondo reale di un fattore 10.
Modifica 2: MS ha corretto il bug. Maggiori informazioni qui: https://connect.microsoft.com/VisualStudio/feedback/details/735731/std-async-std-launch-async-does-not-behave-as-std-thread
"a volte non genera nuovi thread e li esegue in parallelo, ma invece riutilizza i thread ed esegue attività una dopo l'altra" Non è bacato; è così che è permesso lavorare. Non vi è alcuna garanzia nelle specifiche che qualsiasi particolare chiamata asincrona venga eseguita in un thread diverso da chiamate asincrone precedenti o future.Se lo desideri, crea solo un gruppo di thread, incollali in un contenitore e poi unisciti a loro quando vuoi recuperare i dati. –
In futuro, inserire il codice direttamente nella domanda piuttosto che collegarsi a un sito esterno. – ildjarn
@Nicol. Sei sicuro? Come capisco quando uso std :: launch :: async dovrebbe agire come se fosse stato generato un thread. Secondo http://en.cppreference.com/w/cpp/thread/async "Se policy & std :: launch :: async! = 0 (il bit async è impostato), genera un nuovo thread di esecuzione come se std :: thread (f, args ...), tranne che se la funzione f restituisce un valore o genera un'eccezione, viene memorizzato nello stato condiviso accessibile tramite std :: future che async restituisce al chiamante. " – petke