2013-10-17 24 views
13

マクロを介してアクセスされるすべてのスレッドに固有のポインタを格納する必要があります。私は、これをシングルトンと静的なthread_local std :: unique_ptrオブジェクトで解決すべきだと考えました。ここでは、コードの簡易版である:C++ 11:GCC 4.8静的thread_local std :: unique_ptr未定義参照

main.cppには

#include <thread> 
#include <vector> 
#include <iostream> 
#include <mutex> 
using namespace std; 

#include "yay.hpp" 

mutex coutMutex; 

void yay(int id) 
{ 
    int* yayPtr = getYay(); 

    // I know this is bad 
    coutMutex.lock(); 
    cout << "Yay nr. " << id << " address: " << yayPtr << endl; 
    coutMutex.unlock(); 
} 

int main() 
{ 
    vector<thread> happy; 
    for(int i = 0; i < thread::hardware_concurrency(); i++) 
    { 
     happy.push_back(thread(yay, i)); 
    } 

    for(auto& smile : happy) 
    { 
     smile.join(); 
    } 
    return 0; 
} 

yay.hpp

#ifndef BE_HAPPY 
#define BE_HAPPY 

#include <memory> 
class Yay 
{ 
    private: 
     static thread_local std::unique_ptr<int> yay; 
     Yay() = delete; 
     Yay(const Yay&) = delete; 
     ~Yay() {} 
    public: 
     static int* getYay() 
     { 
      if(!yay.get()) 
      { 
       yay.reset(new int); 
      } 
      return yay.get(); 
     } 
}; 

#define getYay() Yay::getYay() 

#endif 

yay.cpp

#include "yay.hpp" 

thread_local std::unique_ptr<int> Yay::yay = nullptr; 

私は、GCC 4.8でこれをコンパイルする場合.1:

g++ -std=c++11 -pthread -o yay main.cpp yay.cpp 

私が手:

/tmp/cceSigGT.o: In function `_ZTWN3Yay3yayE': 
main.cpp:(.text._ZTWN3Yay3yayE[_ZTWN3Yay3yayE]+0x5): undefined reference to `_ZTHN3Yay3yayE' 
collect2: error: ld returned 1 exit status 

私は打ち鳴らすからより多くの情報を得るかもしれない期待していた、しかし、それは打ち鳴らす3.4と完全に正常に動作します:

clang++ -std=c++11 -pthread -o yay main.cpp yay.cpp 

、プログラムを実行しているが、私は期待していた結果が得られます:

Yay nr. 2 address: 0x7fcd780008e0 
Yay nr. 0 address: 0x7fcd880008e0 
Yay nr. 1 address: 0x7fcd800008e0 
Yay nr. 3 address: 0x7fcd700008e0 
Yay nr. 4 address: 0x7fcd740008e0 
Yay nr. 5 address: 0x7fcd680008e0 
Yay nr. 6 address: 0x7fcd6c0008e0 
Yay nr. 7 address: 0x7fcd600008e0 

私は私がここで間違ってやっているかわからないんだけど、静的thread_local unique_ptrをOBJを持ってすることはできませんects?それは、intや '裸の'ポインタのような単純な型で動作します。

編集:

それは、これがhttp://gcc.gnu.org/bugzilla/show_bug.cgi?id=55800

EDIT2に関連しているバグである可能性があります:

回避策1:打ち鳴らすと、一つのファイルをコンパイル(yay.cpp)

回避策2(恐ろしい、移植不可能):最初にアセンブリにyay.cppをコンパイルし、追加する。

.globl _ZTWN3Yay3yayE 
_ZTWN3Yay3yayE = __tls_init 
アセンブリファイルへ

、ファイルをobjectにコンパイルし、残り

+0

'getYay()'のプリプロセッサの置き換えがあなたを混乱させる可能性はありますか? – Tom

+0

#defineを削除してYay :: getYay()を直接呼び出すと機能しません。 – linedot

+0

バグレポートでは、コードのバージョンを大幅に減らし、回避策を示しています。たぶんあなたはそれを答えとして投稿することができます。 –

答えて

2

とのリンク私はYay.hppでイェーイため、何も行わないctorのを定義することによって、このを試し:

 
- Yay() = delete; 
+ Yay() {} 

私はそれをしたときは、エラーメッセージは次のようになりました:

 
/tmp/cc8gDxIg.o: In function `TLS wrapper function for Yay::yay': 
main.cpp:(.text._ZTWN3Yay3yayE[_ZTWN3Yay3yayE]+0x5): undefined reference to `TLS init function for Yay::yay' 

これは私にGCC bug 55800をもたらしました。バグは4.8.2までのGCCバージョンに存在し、4.8.3と4.9で修正されています。私が二重に見つけたディスカッションスレッドでは、GCC bug 59364は、修正を移植しないという決定が下されました。したがって、アセンブラのハックは、4.9に移行するまで利用可能な唯一の解決策です。

関連する問題