2015-03-11 2 views
5

Eines meiner Programme ist das Abhören und Empfangen von Payloads von einem Socket. Ich möchte nie blocken. Für jede empfangene Nutzlast möchte ich ein Objekt erstellen und es an einen Worker-Thread übergeben und es später vergessen, so wie der Prototyp-Code funktioniert. Aber für den Produktionscode möchte ich die Komplexität reduzieren (meine App ist groß), indem ich die bequeme Async-Methode verwende. async nimmt eine Zukunft, die aus einem Versprechen gemacht wird. Damit das funktioniert, muss ich ein Versprechen für mein Nicht-POD-Objekt erstellen, das unten durch die Xxx-Klasse repräsentiert wird. Ich sehe keine Möglichkeit, dies zu tun (siehe Fehler in meinem Beispielcode unten). Ist es angemessen, hier Async zu verwenden? Wenn ja, wie kann ich ein Versprechen/future-Objekt erstellen, die komplexen als int (alle Code-Beispiele Ich habe sehen entweder Verwendung int oder void):kann ein std :: promise von einem Nicht-POD-Objekt gemacht werden?

#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

Haben Sie versucht, 'Xxx' eine Standard-Ctor geben? – Angew

+0

Warum gibst du 'xxx' nicht einfach an die asynchrone Funktion? Brauchen Sie wirklich die Zwei-Wege-Zukunft Kommunikation? Das bedeutet nur, dass beide Threads aufeinander warten. –

+0

Ich verstehe. Da ich bereits die Nutzlastdaten habe, ist es nicht nötig, ein Versprechen/eine Zukunft daraus zu machen. Verwenden Sie einfach den _Fty && _Fnarg, _ArgTypes && ... _Args -Konstruktor von asnyc mit meinen komplexen Argumenten. – rtischer8277

Antwort

5

Wie Mike bereits geantwortet hat, ist es definitiv ein Fehler in der Visual C++ - Implementierung von std::promise, was Sie tun sollten, sollte funktionieren.

Aber ich bin neugierig, warum Sie es trotzdem tun müssen. Vielleicht gibt es eine andere Anforderung, die Sie nicht gezeigt haben, um das Beispiel einfach zu halten, aber das wäre die offensichtliche Möglichkeit, diesen Code zu schreiben:

#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

Ist automatisch xxx = f.get(); immernoch notwendig, da ich in Zukunft nicht mehr vorbeigehen würde? – rtischer8277

+0

Hoppla, gut entdeckt. Ich habe vergessen, dieses Bit zu ändern, es ist jetzt behoben. –

+0

Das ist in der Tat ein Fehler. Ich habe einen [Fehlerbericht] eingereicht (https://connect.microsoft.com/VisualStudio/feedback/details/2229765/bug-std-promise-t-requires- that-t-is- defaultconstructible). Dieser Fehler wird sogar als ein Todo-Element in der -Datei aufgeführt ("// TODO: _Associated_state ctor geht davon aus, dass _Ty standardkonstruierbar ist"), so dass die Entwickler sich dessen bereits bewusst sind. –

3

Es klingt wie Ihre Implementierung defekt ist. Es sollte keinen Standardkonstruktor geben (gemäß den allgemeinen Bibliotheksanforderungen von [Dienstprogramm.Arg.Anforderungen]), und GCC akzeptiert Ihren Code (nach dem Ändern des seltsamen Microsoftish _tmain zu einem Standard main).

Ich würde zu einem anderen Compiler und Betriebssystem wechseln. Das ist vielleicht keine Option für Sie, also könnten Sie der Klasse vielleicht einen Standardkonstruktor geben, um es glücklich zu machen.

+0

Yup, definitiv ein Programmfehler in der Implementierung. 'promise ' sollte einen nicht initialisierten Puffer erstellen und nur ein 'Xxx'-Objekt konstruieren, wenn 'set_value' aufgerufen wird. Eine andere Abhilfe wäre die Verwendung von 'boost :: promise' anstelle von 'std' one –

+0

Ich bin ein C++ MFC-hugger von weit zurück. Ich habe die technischen Java und C# -Technologien übersprungen und bin froh, diese neuen ISO-Parallelisierungsfunktionen zusammen mit all meinen anderen C++ - Bibliotheken (GUI, Verschlüsselung usw.) zu verwenden. Laut Herb Sutter von Build 2014 war es MS, die ihre asynchrone Implementierung der Standard-Community zur Aufnahme einreichte. Ich nehme an, dass [utility.arg.requirements] besagt, dass Sie in der Lage sein sollten, jede Art von Arg in einem Versprechen zu übergeben. – rtischer8277

+1

[utility.arg.requirements] ist nicht spezifisch für 'promise', es sagt nur" Im Allgemeinen ist ein Standardkonstruktor nicht erforderlich. " –

Verwandte Themen