NoS*_*tAl 76 c++ multithreading c++11
c ++ 11有可能获得当前的线程ID,但它不能转换为整数类型:
cout<<std::this_thread::get_id()<<endl;
Run Code Online (Sandbox Code Playgroud)
输出:139918771783456
cout<<(uint64_t)std::this_thread::get_id()<<endl;
Run Code Online (Sandbox Code Playgroud)
错误:从类型'std :: thread :: id'到类型'uint64_t'的无效强制转换与其他类型相同:从类型'std :: thread :: id'到类型'uint32_t'的无效强制转换
我真的不想做指针转换来获取整数线程ID.是否有一些合理的方法(标准因为我希望它是便携式的)来做到这一点?
888*_*888 74
你只需要这样做
std::hash<std::thread::id>{}(std::this_thread::get_id())
Run Code Online (Sandbox Code Playgroud)
得到一个size_t.
的模板专门
std::hash为std::thread::id类允许用户获得线程的标识符的哈希值.
R. *_*des 29
可移植的解决方案是将您自己生成的ID传递给线程.
int id = 0;
for(auto& work_item : all_work) {
std::async(std::launch::async, [id,&work_item]{ work_item(id); });
++id;
}
Run Code Online (Sandbox Code Playgroud)
该std::thread::id类型仅用于比较,而不是用于算术(即,如在can上所述:标识符).通过生产甚至它的文本表示operator<<是未指定的,所以你不能依赖于它是一个数字的表示.
您还可以使用std::thread::id值映射到您自己的id,并在线程之间共享此映射(具有适当的同步),而不是直接传递id.
小智 22
另一个id(想法?^^)将使用stringstreams:
std::stringstream ss;
ss << std::this_thread::get_id();
uint64_t id = std::stoull(ss.str());
Run Code Online (Sandbox Code Playgroud)
如果您在出现问题时不想要例外,请使用try catch ...
一个想法是使用线程本地存储来存储变量 - 无论什么类型,只要它符合线程本地存储的规则 - 然后使用该变量的地址作为"线程ID".显然任何arithemetic都没有意义,但它将是一个完整的类型.
对于后代:
pthread_self()返回a pid_t并且是posix.对于便携式的某些定义,这是便携式的.
gettid(),几乎肯定不是便携式的,但它确实返回了GDB友好的价值.
这样,应该可以工作:
std::stringstream ss;
ss << std::this_thread::get_id();
int id = std::stoi(ss.str());
Run Code Online (Sandbox Code Playgroud)
请记住包含库流
另一种选择:
#include <atomic>
static std::atomic<unsigned long long> thread_counter;
unsigned long long thread_id() {
thread_local unsigned long long tid = ++thread_counter;
return tid;
}
Run Code Online (Sandbox Code Playgroud)
g++ 在 x86 64 位中为此函数生成的代码如下:
_Z9thread_idv:
cmp BYTE PTR fs:_ZGVZ9thread_idvE3tid@tpoff, 0
je .L2
mov rax, QWORD PTR fs:_ZZ9thread_idvE3tid@tpoff
ret
.L2:
mov eax, 1
lock xadd QWORD PTR _ZL14thread_counter[rip], rax
mov BYTE PTR fs:_ZGVZ9thread_idvE3tid@tpoff, 1
mov QWORD PTR fs:_ZZ9thread_idvE3tid@tpoff, rax
ret
_ZGVZ9thread_idvE3tid:
.zero 8
_ZZ9thread_idvE3tid:
.zero 8
Run Code Online (Sandbox Code Playgroud)
即,没有任何同步的单个分支将被正确预测,除非您第一次调用该函数。之后只需一次内存访问而无需同步。
我真的不知道这有多快,但这是我设法猜测的解决方案:
const size_t N_MUTEXES=128;//UINT_MAX,not 128 for answer to my original question
hash<std::thread::id> h;
cout<<h(std::this_thread::get_id())%N_MUTEXES<<endl;
Run Code Online (Sandbox Code Playgroud)
我再次开始认为获取指向结构的指针并将其转换为 unsigned int 或 uint64_t 是答案......编辑:
uint64_t get_thread_id()
{
static_assert(sizeof(std::thread::id)==sizeof(uint64_t),"this function only works if size of thead::id is equal to the size of uint_64");
auto id=std::this_thread::get_id();
uint64_t* ptr=(uint64_t*) &id;
return (*ptr);
}
int main()
{
cout<<std::this_thread::get_id()<<" "<<get_thread_id()<<endl;
}
Run Code Online (Sandbox Code Playgroud)
static_assert 以防止出现地狱般的问题 :) 与寻找此类错误相比,重写更容易。:)
thread::native_handle()returns thread::native_handle_type,它是 的 typedef long unsigned int。
如果线程是默认构造的,则native_handle()返回0。如果有一个操作系统线程附加到它,则返回值非零(POSIX上是pthread_t)。
不使用 thread::get_id() 的一个关键原因是它在单个程序/进程中不是唯一的。这是因为一旦第一个线程完成,该 id 可以重用于第二个线程。
这似乎是一个可怕的功能,但它在 c++11 中是什么。
| 归档时间: |
|
| 查看次数: |
77488 次 |
| 最近记录: |