2

我写了一个模仿java线程的pthread/windows本机线程的包装器。

class Thread{
public:
  virtual void run()=0;
  void start();
  void join();

  virtual ~Thread(){
   join(); 
  }
};

认为

 class B:public Thread{
  int x;     
  void run(){
    while some condition do soemething on x;
  }
};

如果 B 的实例在 run() 返回之前被破坏,线程将继续访问 x,这显然是不可取的。为了解决我需要添加的问题

B::~B(){
 join();
} 

因为 Thread::~Thread() 是在 B::x 被销毁之后调用的,所以 join 没有效果。

但是,如果我有 class C: public B 和一些额外的数据,我仍然需要定义 C::~C(){join();}

依此类推,所有的层次结构

另一种方法是做

template<typename R>
 struct SafeThread:public R,public Thread{
  void run(){
    R::run();
  }
};

这样 R 数据(我们之前的 B::x )将在线程加入后被销毁。然而,仍然

class B{
  virtual void f(){...}
  void run(){ f();}
};


class C:public SafeThread<B>{
  int y;
  void f(){
  ...something on y;
  }

}; 

仍然会有类似的问题。您是否认为有任何优雅的解决方案可以解决在 run 方法终止后确保数据被销毁的问题,而不是强制每个子类 SC 定义 SC::~SC(){join();} ?

4

2 回答 2

1

你可以把你的Thread类写成一个模板,接受任何带有 的类operator(),当Thread::run()被调用时会相应地调用它。下面的代码显示了这个想法。必要时进行更改。

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();
于 2012-05-03T14:48:39.407 回答
1

我认为您只需要使用带有调用连接的基类的虚拟析构函数即可。

例如

class Thread{
public:
  virtual void run()=0;
  void start();
  void join();

protected:
  virtual ~Thread() 
  {
     join( ); 
  }
};
于 2012-05-03T14:31:25.560 回答