S
Savagesmc
Problem Background:
I am working on a thin wrapper for the pthreads interface on linux, and have
encountered frustrating behavior. The idea is to have a "PosixThread" class
that any class can inherit from. A child then only needs to define a
virtual "executive" method that has the thread code for the child object,
and the threading setup and management are automatic then. The thread
creation takes place in the PosixThread base class with a pthread_create
call that gets the address of a static member function that calls the
'executive' function, i.e. the polymorphic executive. The parameter passed
to the static member function is the 'this' pointer which points to the
object being created.
Problem Statement:
The problem I am experiencing is that in a fairly new distro of linux
(mandrake 9.1) calling pthread_create from the base class's constructor
(with this as a parameter) results in a 'pure virtual method called'
run-time error. However, in an older linux distro (redhat 7.3) everything
works as expected.
I suspect that using the 'this' pointer in the Base class's constructor is
probably not something that should be done, with the standard saying if you
do this, you get some kind of undefined behavior. However, I am not a
super-guru yet, therefore the posting here asking for either confirmation or
an explanation.
I've enclosed a sample program that shows both correct and incorrect
behavior. In the distro that gives me errors, if I wait until after the
object has been constructed and call pthread_create from some other method
(like 'thread.start()') then everything works ok, as the this pointer now
has a good virtual method table or something.
The command line command I use to compile this program is:
g++ -o junk junk.cpp -lpthread
It builds in linux or in cygwin. Does not work right in my version of
cygwin either, except no 'pure virtual method called' run-time error.
Thanks in advance for all the help.
Steve
#include <iostream>
#include <iomanip>
#include <pthread.h>
#include <unistd.h>
using namespace std;
class BaseThread {
public:
BaseThread() : started(false) { start(); }
virtual ~BaseThread() { }
void start() {
if (!started) {
started=true;
pthread_create(&id, NULL, BaseThread::hook, this);
}
}
private:
BaseThread& operator=(const BaseThread& val) { }
bool started;
pthread_t id;
virtual void* execute() = 0;
static void* hook(void* b) {
BaseThread* base = (BaseThread*)b;
return base->execute();
}
};
class Thread : virtual public BaseThread {
public:
Thread(bool start=false) : BaseThread() {
// if(start) this->start();
}
virtual ~Thread() { }
private:
Thread& operator=(const Thread& val) { }
virtual void* execute() {
cout << "Child::run" << endl;
return (void*)0;
}
};
class OtherBaseThread {
public:
OtherBaseThread() : started(false) { }
virtual ~OtherBaseThread() { }
void start() {
if (!started) {
started=true;
pthread_create(&id, NULL, OtherBaseThread::hook, this);
}
}
private:
OtherBaseThread& operator=(const OtherBaseThread& val) { }
bool started;
pthread_t id;
virtual void* execute() = 0;
static void* hook(void* b) {
OtherBaseThread* base = (OtherBaseThread*)b;
return base->execute();
}
};
class OtherThread : public OtherBaseThread {
public:
OtherThread(bool start=true) : OtherBaseThread() {
if(start) this->start();
}
virtual ~OtherThread() { }
private:
OtherThread& operator=(const OtherThread& val) { }
virtual void* execute() {
cout << "Child::run" << endl;
return (void*)0;
}
};
int main() {
OtherThread otherThread;
sleep(1);
Thread thread;
sleep(1);
return -1;
}
I am working on a thin wrapper for the pthreads interface on linux, and have
encountered frustrating behavior. The idea is to have a "PosixThread" class
that any class can inherit from. A child then only needs to define a
virtual "executive" method that has the thread code for the child object,
and the threading setup and management are automatic then. The thread
creation takes place in the PosixThread base class with a pthread_create
call that gets the address of a static member function that calls the
'executive' function, i.e. the polymorphic executive. The parameter passed
to the static member function is the 'this' pointer which points to the
object being created.
Problem Statement:
The problem I am experiencing is that in a fairly new distro of linux
(mandrake 9.1) calling pthread_create from the base class's constructor
(with this as a parameter) results in a 'pure virtual method called'
run-time error. However, in an older linux distro (redhat 7.3) everything
works as expected.
I suspect that using the 'this' pointer in the Base class's constructor is
probably not something that should be done, with the standard saying if you
do this, you get some kind of undefined behavior. However, I am not a
super-guru yet, therefore the posting here asking for either confirmation or
an explanation.
I've enclosed a sample program that shows both correct and incorrect
behavior. In the distro that gives me errors, if I wait until after the
object has been constructed and call pthread_create from some other method
(like 'thread.start()') then everything works ok, as the this pointer now
has a good virtual method table or something.
The command line command I use to compile this program is:
g++ -o junk junk.cpp -lpthread
It builds in linux or in cygwin. Does not work right in my version of
cygwin either, except no 'pure virtual method called' run-time error.
Thanks in advance for all the help.
Steve
#include <iostream>
#include <iomanip>
#include <pthread.h>
#include <unistd.h>
using namespace std;
class BaseThread {
public:
BaseThread() : started(false) { start(); }
virtual ~BaseThread() { }
void start() {
if (!started) {
started=true;
pthread_create(&id, NULL, BaseThread::hook, this);
}
}
private:
BaseThread& operator=(const BaseThread& val) { }
bool started;
pthread_t id;
virtual void* execute() = 0;
static void* hook(void* b) {
BaseThread* base = (BaseThread*)b;
return base->execute();
}
};
class Thread : virtual public BaseThread {
public:
Thread(bool start=false) : BaseThread() {
// if(start) this->start();
}
virtual ~Thread() { }
private:
Thread& operator=(const Thread& val) { }
virtual void* execute() {
cout << "Child::run" << endl;
return (void*)0;
}
};
class OtherBaseThread {
public:
OtherBaseThread() : started(false) { }
virtual ~OtherBaseThread() { }
void start() {
if (!started) {
started=true;
pthread_create(&id, NULL, OtherBaseThread::hook, this);
}
}
private:
OtherBaseThread& operator=(const OtherBaseThread& val) { }
bool started;
pthread_t id;
virtual void* execute() = 0;
static void* hook(void* b) {
OtherBaseThread* base = (OtherBaseThread*)b;
return base->execute();
}
};
class OtherThread : public OtherBaseThread {
public:
OtherThread(bool start=true) : OtherBaseThread() {
if(start) this->start();
}
virtual ~OtherThread() { }
private:
OtherThread& operator=(const OtherThread& val) { }
virtual void* execute() {
cout << "Child::run" << endl;
return (void*)0;
}
};
int main() {
OtherThread otherThread;
sleep(1);
Thread thread;
sleep(1);
return -1;
}