11

次の短いプログラムを検討してください。

#include <thread>

int Foo() {
while (1);
}

int main(){
    std::thread t(Foo);
    std::thread s(Foo);

    // (std::thread(Foo));

    t.join();
}

これは、コンパイルして実行します (永久に)。

g++ -Wl,--no-as-needed DoubleBufferTest.cc -o DoubleBufferTest -std=c++0x -pthread

コメントアウトされた行では、ここで説明されている手法を使用して、新しいスレッドを匿名で宣言しようとしています。ただし、その行がコメントインされると、コンパイルできますが、実行すると次のエラーが発生します。

terminate called without an active exception            
Aborted (core dumped)                                   

スレッドを匿名で正しく宣言するにはどうすればよいですか?

注意してください、私はにいg++ 4.4.7ます。

4

3 に答える 3

12

std::threadのデストラクタはstd::terminate、スレッドが結合または分離されていない場合に呼び出されます。

残念ながら、このような匿名スレッド オブジェクトを作成することはできません。またはthreadを呼び出すには、オブジェクトへの参照が必要です。join()detach()

Scott Meyers は、Going Native 2013 で講演を行い、スレッドをラップしてデストラクタで join を呼び出す RAII クラスを作成しました。同様のことができます:

class ThreadRAII {
public:
  ThreadRAII(std::thread&& thread): t(std::move(thread)) {}
  ~ThreadRAII() { if (t.joinable()) { t.join(); }

private:
  std::thread t;
};

詳細については、彼のブログ投稿 またはトークを参照してください。

このように使用できます

(ThreadRAII(std::thread(Foo)));

ただし、この方法でスレッドを作成する唯一の理由は、スレッドがいつ終了するか (または終了するかどうか) を気にしない場合です。したがって、この場合、join はあまり意味がありません。代わりに detach するようにデストラクタを変更する必要があります。

~ThreadRAII() { if (t.joinable()) { t.detach(); }

コメントで示唆されているように、構築時に内部スレッドに完全に転送することで、さらに使いやすくすることができます。

class ThreadRAII2 {
public:    

    template <typename Func, typename ...Args>
    explicit ThreadRAII2(Func&& func, Args&&... args) :
        t(func, std::forward<Args>(args)...) {  }

    ~ThreadRAII2() { 
        if (t.joinable()) t.detach(); 
    }
private:
    std::thread t;
};

その後、元のように使用できます。切り離す必要はありません。

(ThreadRAII2(Foo));

または、Foo引数を取る場合 (例Foo(int): ):

(ThreadRAII2(Foo, 42));
于 2014-01-17T23:35:55.150 に答える
12

次のように実行できます。

std::thread(Foo).detach();
于 2014-01-17T23:41:10.757 に答える
4

これ(あなたが言及しているテクニック)はスレッドでは不可能だと思います。

ここを見てください。

30.3.1.3 スレッドデストラクタ [thread.thread.destr]

〜スレッド();

joinable() の場合はterminate()、それ以外の場合は効果なし。[注: デストラクタで joinable() スレッドを暗黙的にデタッチまたは結合すると、例外が発生した場合にのみ発生する正確性 (デタッチの場合) またはパフォーマンス (結合の場合) バグのデバッグが困難になる可能性があります。したがって、プログラマは、スレッドがまだ結合可能である間はデストラクタが実行されないようにする必要があります。— エンドノート]

基本的に、作成している一時的な匿名オブジェクト (つまりスレッド) は、実行が上記の規則に違反する次の行に続くとすぐに破棄されます。

于 2014-01-17T23:35:19.990 に答える