2012-08-01 12 views
22

Próbuję napisać członka klasy, który wielokrotnie wywołuje innego członka klasy równolegle.Klasa i std :: async na klasie w C++

Napisałem prosty przykład problemu i nie mogę nawet skompilować tego. Co robię źle podczas wywoływania std :: async? Myślę, że problem byłby związany z tym, w jaki sposób przekazuję tę funkcję.

#include <vector> 
#include <future> 
using namespace std; 
class A 
{ 

int a,b; 
public: 
A(int i=1, int j=2){ a=i; b=j;} 

std::pair<int,int> do_rand_stf(int x,int y) 
{ 
    std::pair<int,int> ret(x+a,y+b); 
    return ret; 
} 

void run() 
{ 
    std::vector<std::future<std::pair<int,int>>> ran; 
    for(int i=0;i<2;i++) 
    { 
     for(int j=0;j<2;j++) 
     { 
      auto hand=async(launch::async,do_rand_stf,i,j); 
      ran.push_back(hand);  
     } 
    } 
    for(int i=0;i<ran.size();i++) 
    { 
     pair<int,int> ttt=ran[i].get(); 
     cout << ttt.first << ttt.second << endl; 
    } 
} 
}; 
int main() 
{ 
A a; 
a.run(); 
} 

kompilacja: (. Niejawna this parametru)

g++ -std=c++11 -pthread main.cpp 
+0

przepustkę '* this' jako trzeci parametr' async'. – Xeo

+1

Jeśli pojawią się błędy w kompilacji lub łączeniu, dobrym pomysłem byłoby uwzględnienie tych błędów w pytaniu, najlepiej dosłownym. –

+0

Nie musisz już używać pthread z C++ 11 :) To jest jedno z największych dodatków w C++ 11 (wątkowanie). async() jest niejawnym wątkiem, jeśli asynchroniczne uruchamianie i jawne wątki są tam również w samym języku. – siddhusingh

Odpowiedz

38

do_rand_stf jest non-static funkcji członka, a tym samym nie można nazwać bez instancji klasy szczęście std::async uchwyty jego parametry jak std::bind, i bind z kolei może użyć std::mem_fn, aby zamienić wskaźnik funkcji elementu na funktor, który przyjmuje jawny parametr this, więc wszystko, co musisz zrobić, to przekazać this do std::async inwokacja i użyć właściwego składni wskaźnik funkcji członek przy przejściu do_rand_stf:

auto hand=async(launch::async,&A::do_rand_stf,this,i,j); 

Są też inne problemy w kodzie, choć. Po pierwsze, używasz std::cout i std::endl bez #include ing <iostream>. Bardziej poważnie, std::future nie można kopiować, a jedynie przesuwać, więc nie można używać push_back nazwanego obiektu hand bez używania std::move. Alternatywnie, po prostu przekazać wynik async do push_back bezpośrednio:

ran.push_back(async(launch::async,&A::do_rand_stf,this,i,j)); 
+0

Dzięki, że wszystko rozwiązałeś. :) – UldisK

+0

Bardzo dobre wyjaśnienie @JohannesD – siddhusingh

+0

uratowałeś mi życie. Dzięki – Porizm

1

można przekazać wskaźnik this do nowego wątku:

async([this]() 
{ 
    Function(this); 
}); 
+0

Może brakuje mi czegoś, ale co odróżnia "to" i "to"? Wewnętrzna nić "this" jest taka sama, jak zewnętrzna nić "this", z tym że nie powinno być żadnego wewnętrznego wątku 'this' w ogóle, chyba że schwytany? Brzmi bardziej jak sztuczka javascript ... –

+1

'this_thread :: get_id()' jest sposobem zobaczenia różnicy id wątku, a nie 'tego'. Które nie będą dostępne w lambda, jeśli w ogóle go nie przechwycisz. Tak jak tutaj - http://ideone.com/uWNs4p - musisz jawnie przechwycić 'this'. A jeśli tak, to nie różni się od poza lambdą - http://ideone.com/YuPKf9 –

+1

@ MichaelKrelin-hacker Wygląda na poprawny, przynajmniej z gcc: http://ideone.com/G9icfv którego używałem Visual Studio; to bardzo możliwe, że działa z tym inaczej. – Andrew

Powiązane problemy