función pthread de una clase

Resuelto Angel.King.47 asked hace 15 años • 9 respuestas

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*)'

Angel.King.47 avatar Jul 20 '09 10:07 Angel.King.47
Aceptado

No puede hacerlo de la forma en que lo escribió porque las funciones miembro de la clase C++ tienen un thisparámetro oculto pasado. pthread_create()No tiene idea de qué valor thisusar, 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 thispará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);
Adam Rosenfield avatar Jul 20 '2009 03:07 Adam Rosenfield

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)

Jeremy Friesner avatar Jul 20 '2009 03:07 Jeremy Friesner

Tendrás que dar pthread_createuna 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 cy ejecutar lo que desee en el hilo. pthread_createestá 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]);

    ...
}
Jared Oberhaus avatar Jul 20 '2009 03:07 Jared Oberhaus