2012-08-01 17 views
22

Intento escribir un miembro de clase que llama a otro miembro de clase varias veces en paralelo.Clase y std :: async en miembro de clase en C++

Escribí un ejemplo simple del problema y ni siquiera puedo compilar esto. ¿Qué estoy haciendo mal al llamar a std :: async? Supongo que el problema sería con la forma en que estoy pasando la función.

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

compilación: (. La this parámetro implícito)

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

Pass '* this' como tercer parámetro a' async'. – Xeo

+1

Si obtiene errores en la compilación o en los enlaces, sería una buena idea incluir esos errores en la pregunta, preferiblemente al pie de la letra. –

+0

Ya no necesita usar pthread con C++ 11 :) Esa es una de las adiciones más grandes en C++ 11 (subprocesamiento). async() es un hilo implícito si el lanzamiento asíncrono y el subproceso explícito también están ahí en el lenguaje mismo. – siddhusingh

Respuesta

38

do_rand_stf es una función miembro no estática y por lo tanto no puede ser llamado sin una instancia de clase Afortunadamente, std::async maneja sus parámetros como std::bind, y bind a su vez puede usar std::mem_fn para convertir un puntero de función miembro en un functor que toma un parámetro explícito this, por lo que todo lo que necesita hacer es pasar this al std::async invocación y utilizar la sintaxis de puntero de función miembro válido cuando se pasa el do_rand_stf:

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

Hay otros problemas en el código, sin embargo. En primer lugar, utiliza std::cout y std::endl sin #include ing <iostream>. Más en serio, std::future no se puede copiar, solo se puede mover, por lo que no puede push_back el objeto con nombre hand sin usar std::move. Como alternativa, sólo pasar el resultado a asyncpush_back directamente:

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

Gracias, eso resolvió todo. :) – UldisK

+0

Muy buena explicación @JohannesD – siddhusingh

+0

me salvaste la vida. Gracias – Porizm

1

Puede pasar el puntero this a un nuevo hilo:

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

Tal vez me esté perdiendo algo, pero ¿qué hace que 'this' y 'that' sean diferentes? El 'this' del hilo interno es igual al' this' del hilo externo, excepto que no debería haber ningún hilo interno 'this' en absoluto, a menos que se capturen. Suena más parecido al truco de JavaScript ... –

+1

'this_thread :: get_id()' es una manera de ver la diferencia de identificación de hilo, no 'this'. Que no estará disponible en lambda si no lo capturas en absoluto. Al igual que aquí, http://ideone.com/uWNs4p, debe capturar 'this' explícitamente. Y si lo hace, no es diferente de fuera de lambda: http://ideone.com/YuPKf9 –

+1

@ MichaelKrelin-hacker Parece ser correcto, al menos con gcc: http://ideone.com/G9icfv Estaba usando Estudio visual; es muy posible que funcione de manera diferente con eso. – Andrew

Cuestiones relacionadas