2015-03-11 16 views
5

Una delle cose che fa la mia app è ascoltare e ricevere i carichi utili da un socket. Non voglio mai bloccare. Su ogni payload ricevuto, voglio creare un oggetto e passarlo a un thread di lavoro e dimenticarlo fino a più tardi, ovvero come funziona il codice prototipo. Ma per il codice di produzione voglio ridurre la complessità (la mia app è grande) usando il comodo metodo asincrono. async prende un futuro fatto da una promessa. Per farlo funzionare ho bisogno di creare una promessa sul mio oggetto non POD rappresentato di seguito dalla classe Xxx. Non vedo alcun modo per farlo (vedi errore nel mio codice di esempio qui sotto). È appropriato usare async qui? Se sì, come posso costruire un/oggetto futura promessa che è più complessa di int (tutti gli esempi di codice ho vedono sia per uso int o void):può uno std :: promettere da un oggetto non POD?

#include <future> 
class Xxx //non-POD object 
{ 
    int i; 
public: 
    Xxx(int i) : i(i) {} 
    int GetSquare() { return i * i; } 
}; 

int factorial(std::future<Xxx> f) 
{ 
    int res = 1; 
    auto xxx = f.get(); 
    for(int i = xxx.GetSquare(); i > 1; i--) 
    { 
    res *= i; 
    } 
    return res; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    Xxx xxx(2); // 2 represents one payload from the socket 
    std::promise<Xxx> p; // error: no appropriate default constructor available 
    std::future<Xxx> f = p.get_future(); 
    std::future<int> fu = std::async(factorial, std::move(f)); 
    p.set_value(xxx); 
    fu.wait(); 
    return 0; 
} 
+1

Hai provato a dare a 'Xxx' un ctor predefinito? – Angew

+0

Perché non passi semplicemente 'xxx' alla funzione asincrona? Hai davvero bisogno della comunicazione bidirezionale "futura"? Ciò significa che entrambi i thread si stanno aspettando l'un l'altro. –

+0

Capisco. Poiché ho già i dati del payload, non c'è bisogno di fare una promessa/futuro. Basta usare il costruttore _Fty && _Fnarg, _ArgTypes && ... _Args di asnyc con i miei argomenti complessi. – rtischer8277

risposta

5

Come già detto Mike, è sicuramente un bug nell'implementazione di Visual C++ di std::promise, quello che stai facendo dovrebbe funzionare.

Ma sono curioso perché lo devi fare comunque. Forse c'è qualche altro requisito che non hai dimostrato di mantenere semplice l'esempio, ma questo sarebbe il modo più ovvio per scrivere quel codice:

#include <future> 

class Xxx //non-POD object 
{ 
    int i; 
public: 
    Xxx(int i) : i(i) {} 
    int GetSquare() { return i * i; } 
}; 

int factorial(Xxx xxx) 
{ 
    int res = 1; 
    for(int i = xxx.GetSquare(); i > 1; i--) 
    { 
    res *= i; 
    } 
    return res; 
} 

int main() 
{ 
    Xxx xxx(2); // 2 represents one payload from the socket 
    std::future<int> fu = std::async(factorial, std::move(xxx)); 
    int fact = fu.get(); 
} 
+0

È auto xxx = f.get(); è ancora necessario dal momento che non passerei più in futuro? – rtischer8277

+0

Oops, ben individuato. Ho dimenticato di cambiare quel bit, ora è risolto. –

+0

Questo è davvero un bug. Ho inviato un [bug report] (https://connect.microsoft.com/VisualStudio/feedback/details/2229765/bug-std-promise-t-requires-that-t-is-defaultconstructible). Questo bug è anche elencato come un oggetto todo nel file ("// TODO: _Associated_state ctor assume _Ty è costruibile di default"), quindi gli sviluppatori ne sono già a conoscenza. –

3

suona come l'implementazione è difettoso. Non ci dovrebbe essere bisogno di un costruttore predefinito (secondo i requisiti generali della biblioteca di [utility.arg.requirements]), e GCC accetta il tuo codice (dopo aver cambiato il Microsoftish strano _tmain in uno standard main).

Passarei a un altro compilatore e sistema operativo. Potrebbe non essere un'opzione per te, quindi potresti dare alla classe un costruttore predefinito per renderlo felice.

+0

Sì, sicuramente un bug nell'implementazione. 'promise ' dovrebbe creare un buffer non inizializzato e costruire solo un oggetto 'Xxx' quando viene chiamato' set_value'. Un'altra soluzione sarebbe quella di usare 'boost :: promise' invece di' std' uno –

+0

Sono un hugger MFC C++ di ritorno. Ho saltato le divisioni tecniche di Java e C# e sono felice di utilizzare queste nuove funzionalità di paralellizzazione ISO insieme a tutte le altre mie librerie C++ (GUI, crittografia, ecc.). In realtà, secondo Herb Sutter al 2014 Build, era MS che sottoponeva la loro implementazione asincrona alla comunità degli standard per l'inclusione. Presumo che [utility.arg.requirements] affermi che dovresti essere in grado di passare qualsiasi tipo di argomento in una promessa? – rtischer8277

+1

[utility.arg.requirements] non è specifico per 'promise' ma dice semplicemente" In generale, non è richiesto un costruttore predefinito. " –

Problemi correlati