función pthread de una clase
Digamos que tengo una clase como
class c {
// ...
void *print(void *){ cout << "Hello"; }
}
Y luego tengo un vector de c
vector<c> classes; pthread_t t1;
classes.push_back(c());
classes.push_back(c());
Ahora quiero crear un hilo enc.print();
Y lo siguiente me está dando el siguiente problema:
pthread_create(&t1, NULL, &c[0].print, NULL);
Salida de error: no se puede convertir 'void* (tree_item::*)(void*)' a 'void* (*)(void*)' para el argumento '3' a 'int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(nulo*), nulo*)'
No puede hacerlo de la forma en que lo escribió porque las funciones miembro de la clase C++ tienen un this
parámetro oculto pasado. pthread_create()
No tiene idea de qué valor this
usar, así que si intenta evitar el compilador convirtiendo el método en una función puntero del tipo apropiado, obtendrá un error de segmentación. Tienes que usar un método de clase estático (que no tiene this
parámetros) o una función ordinaria para iniciar la clase:
class C
{
public:
void *hello(void)
{
std::cout << "Hello, world!" << std::endl;
return 0;
}
static void *hello_helper(void *context)
{
return ((C *)context)->hello();
}
};
...
C c;
pthread_t t;
pthread_create(&t, NULL, &C::hello_helper, &c);
Mi forma favorita de manejar un hilo es encapsularlo dentro de un objeto C++. He aquí un ejemplo:
class MyThreadClass
{
public:
MyThreadClass() {/* empty */}
virtual ~MyThreadClass() {/* empty */}
/** Returns true if the thread was successfully started, false if there was an error starting the thread */
bool StartInternalThread()
{
return (pthread_create(&_thread, NULL, InternalThreadEntryFunc, this) == 0);
}
/** Will not return until the internal thread has exited. */
void WaitForInternalThreadToExit()
{
(void) pthread_join(_thread, NULL);
}
protected:
/** Implement this method in your subclass with the code you want your thread to run. */
virtual void InternalThreadEntry() = 0;
private:
static void * InternalThreadEntryFunc(void * This) {((MyThreadClass *)This)->InternalThreadEntry(); return NULL;}
pthread_t _thread;
};
Para usarlo, simplemente crearía una subclase de MyThreadClass con el método InternalThreadEntry() implementado para contener el bucle de eventos de su hilo. Por supuesto, necesitaría llamar a WaitForInternalThreadToExit() en el objeto del hilo antes de eliminar el objeto del hilo (y tener algún mecanismo para asegurarse de que el hilo realmente salga, de lo contrario WaitForInternalThreadToExit() nunca regresaría)
Tendrás que dar pthread_create
una función que coincida con la firma que está buscando. Lo que estás pasando no funcionará.
Puede implementar cualquier función estática que desee para hacer esto, y puede hacer referencia a una instancia c
y ejecutar lo que desee en el hilo. pthread_create
está diseñado para tomar no sólo un puntero de función, sino también un puntero al "contexto". En este caso, simplemente le pasa un puntero a una instancia de c
.
Por ejemplo:
static void* execute_print(void* ctx) {
c* cptr = (c*)ctx;
cptr->print();
return NULL;
}
void func() {
...
pthread_create(&t1, NULL, execute_print, &c[0]);
...
}