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;
  }
};

run()が戻る前にBのインスタンスが破棄された場合、スレッドはxにアクセスし続けますが、これは明らかに望ましくありません。問題を解決するには、追加する必要があります

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

B ::xが破棄された後にThread::〜Thread()が呼び出されるため、joinは効果がありません。

ただし、クラス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();}を定義させることなく、runメソッドの終了後にデータが確実に破棄されるという問題を解決するための洗練されたソリューションがあると思いますか?

4

2 に答える 2

1

結合を呼び出す基本クラスで仮想デストラクタを使用する必要があると思います。

例えば

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

protected:
  virtual ~Thread() 
  {
     join( ); 
  }
};
于 2012-05-03T14:31:25.560 に答える
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 に答える