lin*_*dot 14 c++ gcc clang thread-local-storage c++11
我需要为每个将通过宏访问的线程存储一个唯一的指针.我认为我应该使用单例和静态thread_local std :: unique_ptr对象来解决这个问题.这是代码的简化版本:
#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;
}
Run Code Online (Sandbox Code Playgroud)
#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
Run Code Online (Sandbox Code Playgroud)
#include "yay.hpp"
thread_local std::unique_ptr<int> Yay::yay = nullptr;
Run Code Online (Sandbox Code Playgroud)
如果我用gcc 4.8.1编译它:
g++ -std=c++11 -pthread -o yay main.cpp yay.cpp
Run Code Online (Sandbox Code Playgroud)
我明白了:
/tmp/cceSigGT.o: In function `_ZTWN3Yay3yayE':
main.cpp:(.text._ZTWN3Yay3yayE[_ZTWN3Yay3yayE]+0x5): undefined reference to `_ZTHN3Yay3yayE'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
我希望我可以从clang获得更多信息,但是它与clang 3.4完全一致:
clang++ -std=c++11 -pthread -o yay main.cpp yay.cpp
Run Code Online (Sandbox Code Playgroud)
并运行该程序产生我期望的结果:
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
Run Code Online (Sandbox Code Playgroud)
我不确定我在这里做错了,是不是有可能有静态thread_local unique_ptr对象?它适用于简单类型,如int或'naked'指针.
这可能是与http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55800相关的错误
解决方法1:使用clang编译一个文件(yay.cpp)
解决方法2(可怕且不可移植):首先将yay.cpp编译为程序集,添加
.globl _ZTWN3Yay3yayE
_ZTWN3Yay3yayE = __tls_init
Run Code Online (Sandbox Code Playgroud)
到汇编文件,编译到目标文件,与其余文件链接
我通过在 Yay.hpp 中为 Yay 定义一个不执行任何操作的 ctor 来进行实验:
- 耶()=删除;
+ 耶() {}
当我这样做时,错误消息变成:
/tmp/cc8gDxIg.o:在函数“Yay::yay 的 TLS 包装函数”中: main.cpp:(.text._ZTWN3Yay3yayE[_ZTWN3Yay3yayE]+0x5): 对“Yay::yay 的 TLS 初始化函数”的未定义引用
这导致我发现了GCC bug 55800。该错误存在于 GCC 4.8.2 之前的版本中,并在 4.8.3 和 4.9 中修复。在讨论线程中,我发现重复的GCC bug 59364,已决定不向后移植该修复程序。因此,在升级到 4.9 之前,您的汇编程序 hack 似乎是唯一可用的解决方案。
| 归档时间: |
|
| 查看次数: |
3120 次 |
| 最近记录: |