Posix Thread Wrapper [HELP!!!]

  • Thread starter Sebastian Kloeppel
  • Start date
S

Sebastian Kloeppel

Hi,
i try to write a c++ Posix Thread Wrapper Class. But my virtual Function
doesn't work. Below u see the code :

[thread.h] --------------------

extern "C" {
#include<pthread.h>
}
#include<unistd.h>

#define sout std::cout
#define dout std::cout

class thread;

void* doThread(void* param);

class thread {
private:

friend void* doThread(void* param);
pthread_t tid;


protected:
void* (*todoThread) (void*);
pthread_attr_t tattribute;
bool running;

public:
thread();
thread(void* (*todo)(void*));
thread(void* (*todo)(void*), void* param);

void start(void* param);
void stop(void* status);
void wait();
virtual void mainThread() = 0;
virtual ~thread();
};

// ########## thread ##########

thread::thread() {
running = false;
todoThread = NULL;
pthread_attr_init(&tattribute);
}

thread::thread(void* (*todo)(void*)) {
running = false;
pthread_attr_init(&tattribute);
todoThread = todo;
}

thread::thread(void* (*todo)(void*), void* param) {
running = false;
pthread_attr_init(&tattribute);
todoThread = todo;
start(param);
}

void thread::start(void* param) {
// i do not use the parameter yet ....
if (pthread_create(&tid, &tattribute , doThread, this) != 0) {
dout << "Couldn't create Thread\n";
}
}

void thread::wait() {
if (running) {
pthread_join(tid,NULL);
} else {
dout << "Thread is not running";
}
}

void* doThread(void* param) {
thread* p = (thread*) param;
p->mainThread();
return NULL;
}

void thread::stop(void* status) {
if (running) {
pthread_exit(status);
} else {
dout << "Thread is nor running\n";
}
}

thread::~thread() {
wait();
}





[main.cc] -----------------
#include<iostream>
#include<thread.h>

class athread : public thread {
public:
athread() : thread(NULL,NULL) {
;
}
void mainThread() {
while(true) {
sleep(1);
std::cout << "Thread works";
}
return;
}
};

int main (int argc, char** arqgv) {
athread t1;
t1.wait();
std::cout << "finish\n";
exit(0);
}

//-------------------------------------------------------


After compiling and executing, i get the following result :

pure virtual method called
Aborted

Maybe someone could help and knows why the virtual function isn't
really virtual ...

thanks in advance,
Sebastian Klöppel
 
J

John Harrison

Sebastian Kloeppel said:
Hi,
i try to write a c++ Posix Thread Wrapper Class. But my virtual Function
doesn't work. Below u see the code :

[snip]


After compiling and executing, i get the following result :

pure virtual method called
Aborted

Maybe someone could help and knows why the virtual function isn't
really virtual ...

Because you called it in the constructor of thread.

In the constructor of thread, athread doesn't exist yet, so it's virtual
function cannot be called.

john
 
N

Nick Hounsome

Sebastian Kloeppel said:
Hi,
i try to write a c++ Posix Thread Wrapper Class. But my virtual Function
doesn't work. Below u see the code :

[thread.h] --------------------

extern "C" {
#include<pthread.h>
}
#include<unistd.h>

Why isn't unistd.h in the extern "C" when pthread.h is?

Note that all functions passed to non-C++ libraries must be declared extern
"C"
throughout thus your code is not portable to environments where C and C++
calling
conventions differ and the compiler should have warned you about this (but
I've
never seen it happen either).
#define sout std::cout
#define dout std::cout

Please don't do it.
At worst use
ostream& sout = std::cout;
ostream& dout = std::cout;

Others have explained your error but basically you are going about it the
wrong way.
I know that a lot of people do what you are trying but you cannot logically
encapsulate a
thread and it is not usually useful to try.
The fundamental problems
1. there is always a back door and it is called pthread_self()
2. Logically the destructor of the class should kill the thread. This can be
done for a particular thread
(eg by setting a flag and signalling a cond that the thread waits on)
but is not general. I think we
can agree that pthread_cancel is not the answer. Another problem is that
is not logically
compatible with threads that are created detached or that detach
themselves (see 1).

In my posix wrappers I just use template functions to make pthread_create
type and linkage safe
together with wrapper classes for mutexes and conds and of course the most
useful - a lock.

This allows me to write stuff like
class X
{
static Y* run(X* x) { return x->doRun(); }
Y* doRun()
{
// thread stuff
}
pthread_t tid;
X()
{
PtwThreadAttr attr;
attr.setdetached(true);
tid = myThreadCreate(attr,run,this); // types are deduced from type
of run
}
~X()
{
// signalling and stuff
Y* yp = myThreadJoin<Y*>(tid); // okay it only does a cast
}
}

The trick is (in outline cos I haven't got the code with me and you should
do some work):
1. struct Thunk { void* (*thunkfun)(void* arg); void* arg; }
2. A C function to be the arg to pthread_create:
extern "C" void* cthunkfun(void* p)
{
Thunk* tp = (Thunk*)p;
void* ret = (*p->thunkfun)(tp->arg);
delete tp;
return ret;
}
3. template functions (used as thunkfun above)
template <typename Ret,typename Arg,Ret (*Func)(Arg*) >
void* _myMain(void* varg)
{
return Func((Arg*)varg); // client func
}
4. myThreadCreate
template <typename Ret,typename Arg,Ret (*Func)(Arg*) >
int myThreadCreate(pthread_t*,pthread_attr_t*,Func f,Arg arg)
{
// an exercise for you
}
5. This can be extended to pointers to members etc by deriving from Thunk

I think this is some fairly cool template stuff and does what I want much
better than
a thread class
 
A

Arash Partow

Hi,

Look don't waste your time, just go here:

http://www.partow.net/programming/posixsynchwrapper/index.html

and download the POSIX threading library and be one your way :D



Arash Partow

__________________________________________________
Be one who knows what they don't know,
Instead of being one who knows not what they don't know,
Thinking they know everything about all things.
http://www.partow.net









Nick Hounsome said:
Sebastian Kloeppel said:
Hi,
i try to write a c++ Posix Thread Wrapper Class. But my virtual Function
doesn't work. Below u see the code :

[thread.h] --------------------

extern "C" {
#include<pthread.h>
}
#include<unistd.h>

Why isn't unistd.h in the extern "C" when pthread.h is?

Note that all functions passed to non-C++ libraries must be declared extern
"C"
throughout thus your code is not portable to environments where C and C++
calling
conventions differ and the compiler should have warned you about this (but
I've
never seen it happen either).
#define sout std::cout
#define dout std::cout

Please don't do it.
At worst use
ostream& sout = std::cout;
ostream& dout = std::cout;

Others have explained your error but basically you are going about it the
wrong way.
I know that a lot of people do what you are trying but you cannot logically
encapsulate a
thread and it is not usually useful to try.
The fundamental problems
1. there is always a back door and it is called pthread_self()
2. Logically the destructor of the class should kill the thread. This can be
done for a particular thread
(eg by setting a flag and signalling a cond that the thread waits on)
but is not general. I think we
can agree that pthread_cancel is not the answer. Another problem is that
is not logically
compatible with threads that are created detached or that detach
themselves (see 1).

In my posix wrappers I just use template functions to make pthread_create
type and linkage safe
together with wrapper classes for mutexes and conds and of course the most
useful - a lock.

This allows me to write stuff like
class X
{
static Y* run(X* x) { return x->doRun(); }
Y* doRun()
{
// thread stuff
}
pthread_t tid;
X()
{
PtwThreadAttr attr;
attr.setdetached(true);
tid = myThreadCreate(attr,run,this); // types are deduced from type
of run
}
~X()
{
// signalling and stuff
Y* yp = myThreadJoin<Y*>(tid); // okay it only does a cast
}
}

The trick is (in outline cos I haven't got the code with me and you should
do some work):
1. struct Thunk { void* (*thunkfun)(void* arg); void* arg; }
2. A C function to be the arg to pthread_create:
extern "C" void* cthunkfun(void* p)
{
Thunk* tp = (Thunk*)p;
void* ret = (*p->thunkfun)(tp->arg);
delete tp;
return ret;
}
3. template functions (used as thunkfun above)
template <typename Ret,typename Arg,Ret (*Func)(Arg*) >
void* _myMain(void* varg)
{
return Func((Arg*)varg); // client func
}
4. myThreadCreate
template <typename Ret,typename Arg,Ret (*Func)(Arg*) >
int myThreadCreate(pthread_t*,pthread_attr_t*,Func f,Arg arg)
{
// an exercise for you
}
5. This can be extended to pointers to members etc by deriving from Thunk

I think this is some fairly cool template stuff and does what I want much
better than
a thread class
 

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

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,812
Latest member
GracielaWa

Latest Threads

Top