我编写了一个pthread / windows本机线程的包装器,它模仿java的线程。
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;
}
};
如果在run()返回之前销毁B的实例,则线程将继续访问x,这显然是不合需要的。要解决这个问题,我需要添加
B::~B(){
join();
}
因为在B :: x被销毁之后调用了Thread :: ~Thread(),所以连接没有效果。
但是,如果我有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;
}
};
仍会有类似的问题。 您是否认为有任何优雅的解决方案可以解决在运行方法终止后确保数据被销毁的问题,而不必强制每个子类SC定义SC :: ~SC(){join();}?
答案 0 :(得分:1)
我认为您只需要使用基类调用join的虚拟析构函数。
E.g。
class Thread{
public:
virtual void run()=0;
void start();
void join();
protected:
virtual ~Thread()
{
join( );
}
};
答案 1 :(得分: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();