Reputation: 1326
I wrote a wrapper of pthread / windows native threads which mimics java's threads.
class Thread{
public:
virtual void run()=0;
void start();
void join();
virtual ~Thread(){
join();
}
};
Suppose
class B:public Thread{
int x;
void run(){
while some condition do soemething on x;
}
};
If an instance of B is destructed before run() returns, the thread will keep accessing x, and this is clearly undesirable. To solve the problem I need to add
B::~B(){
join();
}
because Thread::~Thread() is called after B::x is destroyed, so that join would have no effect.
However, if I have class C: public B with some additional data, I still need to define C::~C(){join();}
And so forth, all down the hierarchy
An alternative would be to do
template<typename R>
struct SafeThread:public R,public Thread{
void run(){
R::run();
}
};
so that R data (our previous B::x ) would be destroyed after the thread has joined. However, still
class B{
virtual void f(){...}
void run(){ f();}
};
class C:public SafeThread<B>{
int y;
void f(){
...something on y;
}
};
would still have similar problems. Do you think there's any elegant solution for solving the problem of assuring data are destroyed after the run method terminates, without forcing every subclass SC to define SC::~SC(){join();} ?
Upvotes: 2
Views: 299
Reputation: 827
you may write your Thread
class as a template accepting any class with operator()
, which is called accordingly when Thread::run()
is called. The code below shows the idea. Make changes if necessary.
template<typename T>
class MyThread
{
T & _obj;
MyThread() = delete;
MyThread(T& o) : _obj(o) {}
void run()
{
_obj();
}
// other member functions
};
struct B {
int data_to_process;
void operator()() {
// do something with data
}
}
// usage
B b;
MyThread<B> t(b);
t.run();
Upvotes: 1
Reputation: 25799
I think you just need to use a virtual destructor with the base class calling join.
E.g.
class Thread{
public:
virtual void run()=0;
void start();
void join();
protected:
virtual ~Thread()
{
join( );
}
};
Upvotes: 1