9

私はクラスXを持っています:

class X { ... }

私はこれをしたい:

void f()
{
    thread_local static X x = ...;

    ...
}

(実際にはgccを使用しているので、キーワードは「__thread」です)

しかし、あなたは些細なthread_localsしか持てないので、私はできません。

これに対する最善の回避策は何ですか?

私がこのようにすると:

void f()
{
    thread_local static X* p = 0;

    if (!p)
       p = new X(...);

    X& x = *p;

    ...
}

それから:

  1. スレッドが終了するときにデストラクタは呼び出されません
  2. 不要な動的メモリ割り当て。

アップデート:

これが私がこれまでに持っているものです:

#include <iostream>
#include <type_traits>

using namespace std;

class X { public: X() { cout << "X::X()" << endl; }; ~X() { cout << "X::~X()" << endl; } };

void f()
{
        static __thread bool x_allocated = false;
        static __thread aligned_storage<sizeof(X),
             alignment_of<X>::value>::type x_storage;

        if (!x_allocated)
        {
                new (&x_storage) X;
                x_allocated = true;
                // add thread cleanup that calls destructor
        }

        X& x = *((X*) &x_storage);
}

int main()
{
        f();
}

これにより、動的メモリ割り当ての問題が修正されます。スレッドクリーンアップハンドラーを追加する必要があります。pthreadでこれを行うメカニズムはありますか?

4

2 に答える 2

6

規格では、§7.1.1 で他のもの ( など) と同様thread_localにストレージ指定子として説明しています。その単語の定義による「単純な」データ型への制限はありません。staticextern

この問題は、C++11 より前のディスカッション ドキュメント N2147で簡単に説明されています(「スレッド変数の動的初期化」セクションを参照)。これには、適切な実装に関係する主要な問題の説明が含まれています。どうやら GCC 実装 ( static __thread) はこれらの問題をまだ解決していません (これは、GCC が C++11 を正式にサポートしていないという事実と一致していますthread_local)。

1 つの代替案は、この以前の投稿boost::thread_specfic_ptr<>で言及されており、ここで説明されています。

もう 1 つの方法は、std::threadオブジェクトを使用してスレッドを実装し、各インスタンスが変数の独自のコピーを保持するようにすることunique_ptrです。

于 2012-08-21T06:26:26.713 に答える
6

thread_local実際、__thread同じものではありません。それらの主な違いは、まさにあなたが偶然見つけたものです-thread_local変数を非PODにすることができます。残念ながら、これにはパフォーマンスへの影響もあります。これらのパフォーマンスへの影響の詳細については、この質問を参照してください。

于 2013-07-12T07:44:28.023 に答える