From: Adriano Melo on
It's my first post on this list.. can anyone help me?

i have a very simple class that creates threads on linux, but it
doesnt work.
i tried this code and using 'extern "C" void* functionToRun(void*
argc);' but this one shows a linker error.
code:
========= Runnable.h ==============
#include <iostream>
#ifndef RUNNABLE
#define RUNNABLE
struct cRunnable{
virtual void* run(void* argc) = 0;
};
class Runnable:public cRunnable{
public:
Runnable(){}
virtual void run(){
std::cout << "Thread Ativa, mas com o método padrão não
sobreescrito" << std::endl;
}
void* run(void* argc){
this->run();
}
};
#endif
============== ThreadsControler.cpp =============
#include "Runnable.h"
#include <pthread.h>
#ifndef CONTROLADOR_DE_THREADS
#define CONTROLADOR_DE_THREADS
class ControladorDeThreads {
pthread_t* threads;
int index;
public:
ControladorDeThreads(int numeroMaximoDeThreads){
threads = (pthread_t*)malloc(numeroMaximoDeThreads *
sizeof(pthread_t));
index = 0;
}
void adicionarThread(Runnable* thread){
int rc = pthread_create(&threads[index], NULL, (void*)thread-
>run, (void *)thread);
this->index += 1;

if (rc){
std::cout << "ERROR; return code from pthread_create() is "
<< rc << std::endl;
}
}
void finalizarExecucaoDasThreads(){
pthread_exit(NULL);
}
};
#endif
From: Ulrich Eckhardt on
Adriano Melo wrote:
> i tried this code and using 'extern "C" void* functionToRun(void*
> argc);' but this one shows a linker error.

Which one? Seriously, in order to demonstrate a problem, remove as much code
as possible. Typically, the only thing that remains is main() and a little
more code. Also, in your code below there is no 'extern "C"', so what is
the point here?

> struct cRunnable{
> virtual void* run(void* argc) = 0;
> };

I guess (I don't know, since it isn't documented) that this is wrong. The
function used with pthread_create takes a void* in order to be able to pass
some arbitrary context to the newly-started thread. In the case of a class'
memberfunction, you have the instance as a context (via the 'this'
pointer). This is also a basic and very important difference between a
normal function and a memberfunction and explained in the FAQ at
parashift's.

> class Runnable:public cRunnable{
[...]
> void* run(void* argc){
> this->run();
> }
> };

Try creating such an object and call its run() memberfunction. I also wonder
why this code doesn't throw warnings, did you forget to activate them?


> threads = (pthread_t*)malloc(numeroMaximoDeThreads *
> sizeof(pthread_t));

Wrong. Firstly, please forget that C-style casts ("(type)object") casts
exist at all. These don't serve much in C++ but to make something compile
that breaks at runtime then. Secondly, std::vector<pthread_t> would be much
better. However, in a simple example, you don't need several threads, see
my initial remark.

Note that once you removed all C-style casts, you code will not compile any
more and that is good, because it is broken. Fix those one by one and not
only will it compile but also work correctly.

> pthread_create( &threads[index],
> NULL,
> (void*)thread->run,
> (void *)thread);

Note: you can not convert a memberfunction to a function suitable for
pthread_create like that. You need an additional non-member function.

Uli

From: Ian Collins on
Ulrich Eckhardt wrote:
> Adriano Melo wrote:
>
>> pthread_create( &threads[index],
>> NULL,
>> (void*)thread->run,
>> (void *)thread);
>
> Note: you can not convert a memberfunction to a function suitable for
> pthread_create like that. You need an additional non-member function.
>
With C linkage.

--
Ian Collins.