pthreads

A

Arnd Schroeter

Hello!

I am a c++ programmer under the os linux. I am using pthreads and i am
wondering why i can only use satic methods of a class to create a
thread of it. How can i change this, because it limits my programmes
very strongly. thanks in advance..Arnd Schröter
 
R

Rolf Magnus

Arnd said:
Hello!

I am a c++ programmer under the os linux. I am using pthreads and i am
wondering why i can only use satic methods of a class to create a
thread of it. How can i change this, because it limits my programmes
very strongly. thanks in advance..Arnd Schröter

Threads are off-topic here, but I think your question is actually not
about threads, but about using callbacks in C with a C++ function.

Non-static member functions cannot be used. They need to be called for
an object, and how would the pthreads library know which object to call
the member function for? Further, the pthreads library is C, and so it
doesn't even know about objects and member functions.
Regarding static member functions: Actually, those probably work on many
platforms, but this is not guarranteed. You need to make your callback
function a non-member function that is declared extern "C" or be sure
that all platforms/compiler combinations you want to support have the
same calling conventions for C and C++.

There is still a way to call a member function, indirectly. pthreads,
like any other C library with a callback interface (at least those I
that know), provide an additional parameter of type void* that is
passed to the callback function. You can use that pointer to pass your
object. Something like this (untested and unfinished) should show you
the idea:


class Thread
{
public:
Thread();
//...
virtual void run() = 0;
//...
private:
pthread_t id_;
};

//pthread_create needs void* both for parameter and return type
extern "C"
void* thread_routine(void* obj)
{
static_cast<Thread*>(obj)->run();
return obj; //or whatever else you might need
}

Thread::Thread()
{
pthread_create(&_id, 0, thread_routine, this);
}
 
D

David Harmon

I am a c++ programmer under the os linux. I am using pthreads and i am
wondering why i can only use satic methods of a class to create a
thread of it. How can i change this, because it limits my programmes
very strongly. thanks in advance..Arnd Schröter

ptreads is not part of C++, so I can only assume that it is the usual
reason for such a restriction: Your function is going to be called from
code that is not C++ and does not have any provision to pass a 'this'
pointer to a member function. In many cases the designers of such
things provide an extra generic argument, e.g. a long, into which you
can cram the required 'this' pointer with lots of unsafe casting and
glue.

For comparison, see the topic "[30.2] How do I pass a pointer to member
function to a signal handler, X event callback, etc?" in Marshall
Cline's C++ FAQ. It is always good to check the FAQ before posting.
You can get the FAQ at:
http://www.parashift.com/c++-faq-lite/
 
A

Ahti Legonkov

Arnd said:
I am a c++ programmer under the os linux. I am using pthreads and i am
wondering why i can only use satic methods of a class to create a
thread of it. How can i change this, because it limits my programmes
very strongly. thanks in advance..Arnd Schröter

The non-static member functions have different signature, that's why.
And you can't change that. You have to work your way around it. One
possible workaround is like this:


struct thread
{
static void thread_func(void* p);
virtual void run() = 0;
};

void thread::thread_func(void* p) {
// iirc pthread_create needs a function that takes a void
// pointer.
thread* t = reinterpret_cast<thread*>(p);
t->run();
}

struct some_thread : thread {
void run() {
// do your stuff..
}
};

thread* thr = new some_thread();

Now pass thread::thread_func to the thread creation function as start
routine and thr as argument to start routine.
 
N

Nick Hounsome

Rolf Magnus said:
Threads are off-topic here, but I think your question is actually not
about threads, but about using callbacks in C with a C++ function.

Non-static member functions cannot be used. They need to be called for
an object, and how would the pthreads library know which object to call
the member function for? Further, the pthreads library is C, and so it
doesn't even know about objects and member functions.
Regarding static member functions: Actually, those probably work on many
platforms, but this is not guarranteed. You need to make your callback
function a non-member function that is declared extern "C" or be sure
that all platforms/compiler combinations you want to support have the
same calling conventions for C and C++.

There is still a way to call a member function, indirectly. pthreads,
like any other C library with a callback interface (at least those I
that know), provide an additional parameter of type void* that is
passed to the callback function. You can use that pointer to pass your
object. Something like this (untested and unfinished) should show you
the idea:


class Thread
{
public:
Thread();
//...
virtual void run() = 0;
//...
private:
pthread_t id_;
};

//pthread_create needs void* both for parameter and return type
extern "C"
void* thread_routine(void* obj)
{
static_cast<Thread*>(obj)->run();
return obj; //or whatever else you might need
}

You really want this to be:
extern "C"
void* thread_routine(void* obj) throw()
{
try {
static_cast<Thread*>(obj)->run();
return obj; //or whatever else you might need
}
catch(...)
{
// return error code or just exit
}
}

because it is undefined what will happen if you allow the main thread
function to throw an exception.
Thread::Thread()
{
pthread_create(&_id, 0, thread_routine, this);
}

P.S. The whole idea of a thread class is probably bad modelling since the
lifetime of the thread is not linked to the lifetime of the object without
quite a lot of fancy stuff.

Problems are:
1. A destructor absolutely must call pthread_join or the lifetime of the
thread is longer than that of the object - this in turn means that the
thread cannot be detached and also that a call to the destructor might never
return.
2. It is possible for the thread to start, do its job and exit before the
creating thread even returns from pthread_create i.e. you may well need a
condition to be signalled from the thread to the ctor to indicate that it is
realy going.

Mostly I model at a higher level of abstraction - for example a Worker
object that accepts Jobs with virtual run methods and runs them.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top