2012-08-01 18 views
22

Sto provando a scrivere un membro della classe che chiama un altro membro della classe più volte in parallelo.Class e std :: async sul membro della classe in C++

Ho scritto un semplice esempio del problema e non riesco nemmeno a compilarlo. Cosa sto facendo di sbagliato nel chiamare std :: async? Credo che il problema sarebbe con come sto passando la funzione.

#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(); 
} 

compilazione: (. Il parametro implicito this)

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

Passo '* this' come terzo parametro a' async'. – Xeo

+1

Se ricevi errori nella compilazione o nel collegamento, sarebbe una buona idea includere quegli errori nella domanda, preferibilmente testualmente. –

+0

Non hai più bisogno di usare pthread con C++ 11 :) Questa è una delle maggiori aggiunte in C++ 11 (threading). async() è un thread implicito se il lancio asincrono e il threading esplicito sono presenti anche nella lingua stessa. – siddhusingh

risposta

38

do_rand_stf è una funzione membro non statica e quindi non può essere chiamato senza un'istanza di classe Fortunatamente, std::async maniglie suoi parametri come std::bind, e bind a sua volta può utilizzare std::mem_fn per trasformare un puntatore a funzione membro in un functor che assume un parametro esplicito this, quindi tutto ciò che devi fare è passare this a std::async invocazione e utilizzare la sintassi valida puntatore a funzione membro quando passa il do_rand_stf:

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

Ci sono altri problemi nel codice, però. Innanzitutto, si utilizza std::cout e std::endl senza #include ing <iostream>. Più seriamente, std::future non è copiabile, solo mobile, quindi non è possibile hand l'oggetto denominato hand senza utilizzare std::move. In alternativa, basta passare il risultato async-push_back direttamente:

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

Grazie, questo ha risolto tutto. :) – UldisK

+0

Ottima spiegazione @JohannesD – siddhusingh

+0

mi hai salvato la vita. Grazie – Porizm

1

È possibile passare il puntatore this ad un nuovo thread:

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

Forse mi manca qualcosa, ma cosa rende 'this' e' that' diverso? Il filo interno "questo" è lo stesso del filo esterno "questo", eccetto che non ci dovrebbe essere alcun filo interno "questo", a meno che non sia catturato? Sembra più un trucco javascript ... –

+1

'this_thread :: get_id()' è un modo per vedere la differenza dell'id di thread, non 'this'. Che non sarà disponibile in lambda se non lo catturi affatto. Come qui - http://ideone.com/uWNs4p - è necessario acquisire 'this' esplicitamente. E se lo fai, non è diverso rispetto a lambda - http://ideone.com/YuPKf9 –

+1

@ MichaelKrelin-hacker Sembra che tu abbia ragione, almeno con gcc: http://ideone.com/G9icfv stavo usando Visual Studio; è molto probabile che funzioni diversamente con quello. – Andrew

Problemi correlati