2015-03-11 5 views
5

Jedną z rzeczy, którą robi moja aplikacja, jest słuchanie i odbieranie ładunków z gniazda. Nigdy nie chcę blokować. Na każdym odebranym ładunku, chcę utworzyć obiekt i przekazać go do wątku roboczego i zapomnieć o nim dopiero później, jak działa prototypowy kod. Ale dla kodu produkcyjnego chcę zmniejszyć złożoność (moja aplikacja jest duża) za pomocą wygodnej metody asynchronicznej. async bierze przyszłość z obietnicy. Aby to działało, muszę utworzyć obietnicę na moim obiekcie nie-POD reprezentowanym poniżej przez klasę Xxx. Nie widzę sposobu, aby to zrobić (zobacz błąd w moim przykładowy kod poniżej). Czy warto tutaj używać asynchronicznego? Jeśli tak, to w jaki sposób można skonstruować obietnica/przyszłego obiektu, który jest bardziej skomplikowane niż int (wszystkie przykłady kodu mam zobaczyć użyć int lub void):Czy std :: obietnica może być wykonana z obiektu innego niż 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

Czy próbowałeś dać 'Xxx' domyślnemu ctorowi? – Angew

+0

Dlaczego po prostu nie przekazujesz 'xxx' do funkcji asynchronicznej? Czy naprawdę potrzebujesz dwukierunkowej komunikacji "przyszłościowej"? Oznacza to po prostu, że oba wątki czekają na siebie nawzajem. –

+0

Rozumiem. Ponieważ mam już dane dotyczące ładunku, nie ma potrzeby składania obietnicy/przyszłości. Po prostu użyj konstruktora asnyca _Fty && _Fnarg, _ArgTypes && ... _Args z moimi złożonymi argumentami. – rtischer8277

Odpowiedz

5

Jak Mike już odpowiedział, to na pewno błąd w implementacji Visual C++ z std::promise, to, co robisz, powinno zadziałać.

Ale jestem ciekawy, dlaczego i tak trzeba to zrobić. Może jest jeszcze jakiś inny wymóg, którego nie pokazałeś, aby przykład był prosty, ale byłby to oczywisty sposób napisania tego kodu:

#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

Is auto xxx = f.get(); nadal konieczne, ponieważ nie będę już dłużej przechodził w przyszłości? – rtischer8277

+0

Ups, dobrze zauważył. Zapomniałem zmienić ten bit, to jest teraz naprawione. –

+0

To jest rzeczywiście błąd. Przesłałem [zgłoszenie błędu] (https://connect.microsoft.com/VisualStudio/feedback/details/2229765/bug-std-promise-t-requires-that-t-is-defaultconstructible). Ten błąd jest nawet wymieniony jako element todo w pliku ("// TODO: _Associated_state ctor zakłada, że ​​_Ty jest domyślną konstrukcją"), więc programiści już to dobrze wiedzą. –

3

Brzmi jak implementacja jest uszkodzony. Nie powinno być potrzeby domyślnego konstruktora (zgodnie z ogólnymi wymaganiami biblioteki [utility.arg.requirements]), a GCC akceptuje twój kod (po zmianie dziwnego Microsoftish _tmain na standardowy main).

Przestawiłbym się na inny kompilator i system operacyjny. To może nie być opcja dla ciebie, więc może możesz dać klasie domyślny konstruktor, aby był szczęśliwy.

+0

Tak, zdecydowanie błąd w implementacji. 'obietnica ' powinna utworzyć niezainicjowany bufor i skonstruować obiekt 'Xxx' tylko wtedy, gdy wywołana zostanie' set_value'. Innym obejściem byłoby użycie 'boost :: promise' zamiast' std' one –

+0

Jestem mob-C++ C++ od drogi powrotnej. Pominąłem techniczne odchylenia w Javie i C# i cieszę się, że mogę wykorzystać te nowe możliwości paralelizacji ISO wraz z wszystkimi moimi innymi bibliotekami C++ (GUI, szyfrowanie itp.). W rzeczywistości, zgodnie z Herb Sutter w 2014 Build, to MS złożyło swoje asynchroniczne wdrożenie do społeczności standardów w celu włączenia. Zakładam, że [utility.arg.requirements] stwierdza, że ​​powinieneś być zdolny do przekazania jakiegokolwiek rodzaju argumentu w obietnicy? – rtischer8277

+1

[utility.arg.requirements] nie jest specyficzne dla "obietnicy", która brzmi "Ogólnie rzecz biorąc, domyślny konstruktor nie jest wymagany." –

Powiązane problemy