Fabio Dalla Libera
Fabio Dalla Libera

Reputation: 1326

thread as class, how to assure data of subclasses being destroyed after?

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

Answers (2)

user2k5
user2k5

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

Nick
Nick

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

Related Questions