2009-11-11 11 views
6

tengo una clase trabajadora como la siguiente:Obteniendo el valor de retorno de una función boost :: threaded member?

class Worker{ 
public: 
    int Do(){ 
    int ret = 100; 
    // do stuff 
    return ret; 
    } 
} 

Está pensado para ser ejecutado con impulso :: hilo y boost :: bind, como:

Worker worker; 
boost::function<int()> th_func = boost::bind(&Worker::Do, &worker); 
boost::thread th(th_func); 
th.join(); 

Mi pregunta es, ¿cómo Obtengo el valor de retorno de Worker :: Do?

Gracias de antemano.

Respuesta

7

No creo que pueda obtener el valor de retorno.

su lugar, puede almacenar el valor como miembro del Trabajador:

class Worker{ 
public: 
    void Do(){ 
    int ret = 100; 
    // do stuff 
    m_ReturnValue = ret; 
    } 
    int m_ReturnValue; 
} 

y usarlo de esta manera:

Worker worker; 
boost::function<void()> th_func = boost::bind(&Worker::Do, &worker); 
boost::thread th(th_func); 
th.join(); 
//do something with worker.m_ReturnValue 
+0

Gracias, supongo que tengo que rediseñar un poco. –

2

Además, también tiene algunas llamadas redundantes para impulsar :: bind() y boost :: function(). En su lugar, puede hacer lo siguiente:

class Worker{ 
    public: 
     void operator(){ 
      int ret = 100; 
      // do stuff 
      m_ReturnValue = ret; 
     } 
    int m_ReturnValue; 
} 

Worker worker; 
boost::thread th(worker());//or boost::thread th(boost::ref(worker)); 

Usted puede hacer esto porque el constructor de Thread es una envoltura alrededor de un aprieto conveniencia interna() llamada. Thread Constructor with arguments

+0

Eso parece bastante sencillo. Gracias, pero mi implementación real contiene muchas funciones miembro, por lo que realmente no puedo usar el operador(). –

+0

@He Shiming: Aún puede usarlo sin bind(). Por ejemplo, boost :: thread (worker(), & Worker :: Do) (La sintaxis puede estar un poco apagada ya que es la parte superior de mi cabeza). –

-2

Otra opción es utilizar la biblioteca Boost.Lambda. A continuación, puede escribir el código como sigue sin cambiar la clase Worker:

Worker worker; 
int ret; 
boost::thread th(boost::lambda::var(ret) = worker.Do()); 
th.join(); 

Esto es útil, en particular cuando no se puede cambiar la función a llamar. De esta manera, el valor de retorno se envuelve en una variable local ret.

+4

Esto ejecutará 'worker.Do()' en el hilo actual, copia el resultado en un objeto lambda, ejecuta ese lambda en el nuevo hilo (asignando así el resultado de 'worker.Do()' a 'ret'), y luego espere a que se complete la ejecución del nuevo hilo. Es probable que ** no ** sea el comportamiento deseado, ya que ejecuta 'worker.Do()' en el hilo equivocado. La manera más fácil y correcta de obtener resultados de una función ejecutada en un hilo diferente es usar futuros y promesas. – Mankarse

13

Otra opción es usar promesas/futuros.

class Worker{ 
public: 
    void Do(boost::promise<int> & p){ 
    int ret = 100; 
    // do stuff 
    p.set_value(ret); 
    } 
}; 
//Later... 
boost::promise<int> p; 
boost::thread t(boost::bind(&Worker::Do, &worker, boost::ref(p)); 
int retval = p.get_future().get(); //This will block until the promise is set. 

Y si se puede usar C++ 0x, a continuación, utilizando std :: asíncrono será empaquetar todo lo anterior y sólo hacer:

std::future<int> f = std::async(std::bind(&Worker::Do, &worker)); 
int retval = f.get(); //Will block until do returns an int. 
1
class Worker{ 
public: 
    int Do(){ 
    int ret = 100; 
    // do stuff 
    return ret; 
    } 
} 

Worker worker; 
boost::packaged_task<int> ptask(boost::bind(&Worker::Do, &worker)); 
boost::unique_future<int> future_int = ptask.get_future(); 
boost::thread th(boost::move(ptask)); 
th.join(); 
if (future_int.is_ready()) 
    int return_value = future_int.get(); 

Usted puede echar un vistazo a el concepto "boost :: future" ref ref. link

Cuestiones relacionadas