C++ 如何在c ++ 11中获取整数线程ID
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7432100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get integer thread id in c++11
提问by NoSenseEtAl
c++11 has a possibility of getting current thread id, but it is not castable to integer type:
c++11 有获取当前线程 id 的可能性,但它不能转换为整数类型:
cout<<std::this_thread::get_id()<<endl;
output : 139918771783456
输出:139918771783456
cout<<(uint64_t)std::this_thread::get_id()<<endl;
error: invalid cast from type ‘std::thread::id' to type ‘uint64_t' same for other types: invalid cast from type ‘std::thread::id' to type ‘uint32_t'
错误:从类型 'std::thread::id' 到类型 'uint64_t' 的无效转换对于其他类型相同:从类型 'std::thread::id' 到类型 'uint32_t' 的无效转换
I really dont want to do pointer casting to get the integer thread id. Is there some reasonable way(standard because I want it to be portable) to do it?
我真的不想做指针转换来获取整数线程 id。是否有一些合理的方法(标准,因为我希望它是便携式的)来做到这一点?
采纳答案by R. Martinho Fernandes
The portable solution is to pass your own generated IDs into the thread.
可移植的解决方案是将您自己生成的 ID 传递到线程中。
int id = 0;
for(auto& work_item : all_work) {
std::async(std::launch::async, [id,&work_item]{ work_item(id); });
++id;
}
The std::thread::id
type is to be used for comparisons only, not for arithmetic (i.e. as it says on the can: an identifier). Even its text representation produced by operator<<
is unspecified, so you can't rely on it being the representation of a number.
该std::thread::id
类型仅用于比较,而不用于算术(即如罐头上所说:标识符)。甚至它产生的文本表示operator<<
是unspecified,所以你不能依赖它是一个数字的表示。
You could also use a map of std::thread::id
values to your own id, and share this map (with proper synchronization) among the threads, instead of passing the id directly.
您还可以使用std::thread::id
值映射到您自己的 id,并在线程之间共享此映射(具有适当的同步),而不是直接传递 id。
回答by 888
You just need to do
你只需要做
std::hash<std::thread::id>{}(std::this_thread::get_id())
to get a size_t
.
得到一个size_t
.
From cppreference:
The template specialization of
std::hash
for thestd::thread::id
class allows users to obtain hashes of the identifiers of threads.
的模板专门
std::hash
为std::thread::id
类允许用户获得线程的标识符的哈希值。
回答by Mike
Another id (idea? ^^) would be to use stringstreams:
另一个 id(想法?^^)将使用字符串流:
std::stringstream ss;
ss << std::this_thread::get_id();
uint64_t id = std::stoull(ss.str());
And use try catch if you don't want an exception in the case things go wrong...
如果您不想在出现问题的情况下出现异常,请使用 try catch ...
回答by tgoodhart
One idea would be to use thread local storage to store a variable - doesn't matter what type, so long as it complies with the rules of thread local storage - then to use the address of that variable as your "thread id". Obviously any arithemetic will not be meaningful, but it will be an integral type.
一种想法是使用线程本地存储来存储变量——不管是什么类型,只要它符合线程本地存储的规则——然后使用该变量的地址作为你的“线程ID”。显然任何算术都没有意义,但它将是一个整数类型。
For posterity:
pthread_self()
returns a pid_t
and is posix. This is portable for some definition of portable.
对于后代:
pthread_self()
返回 apid_t
并且是 posix。对于可移植的某些定义,这是可移植的。
gettid()
, almost certainly not portable, but it does return a GDB friendly value.
gettid()
,几乎可以肯定不是可移植的,但它确实返回了 GDB 友好值。
回答by Alexey Polonsky
thread::native_handle()
returns thread::native_handle_type
, which is a typedef to long unsigned int
.
thread::native_handle()
返回thread::native_handle_type
,这是一个类型定义到long unsigned int
.
If thread is default constructed, native_handle() returns 0. If there is an OS thread attached to it, the return value is non-zero (it is pthread_t on POSIX).
如果线程是默认构造的,则 native_handle() 返回 0。如果有操作系统线程附加到它,则返回值非零(在 POSIX 上是 pthread_t)。
回答by NoSenseEtAl
I really dont know how fast is this, but this is the solution I managed to guestimate :
我真的不知道这有多快,但这是我设法猜测的解决方案:
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;
Again I'm starting to think that getting a pointer to the structure and casting it to unsigned int or uint64_t is the answer... EDIT:
我再次开始认为获取指向结构的指针并将其转换为 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;
}
static_assert to prevent hellish problems :) Rewrite is easy compared to hunting down this kind of bug. :)
static_assert 以防止出现地狱般的问题 :) 与寻找此类错误相比,重写更容易。:)
回答by Federico Rizzo
In this way, should work:
这样,应该工作:
std::stringstream ss;
ss << std::this_thread::get_id();
int id = std::stoi(ss.str());
Remember to include library sstream
记得包含库 sstream
回答by Pandrei
it depends on what you what you want to use the thread_id for; you can use:
这取决于你想用 thread_id 做什么;您可以使用:
std::stringstream ss;
ss << std::this_thread::get_id();
uint64_t id = std::stoull(ss.str());
This will generate a unique id withing you process; but there's a limitation: if you launch several instances of the same process and each one of them writes their thread ids to a common file, the uniqueness of the thread_id is not guaranteed; in fact it's very likely you'll have overlaps. In this case you can do something like:
这将在您处理过程中生成一个唯一的 ID;但是有一个限制:如果您启动同一进程的多个实例,并且每个实例都将其线程 ID 写入一个公共文件,则无法保证 thread_id 的唯一性;事实上,你很可能会有重叠。在这种情况下,您可以执行以下操作:
#include <sys/time.h>
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
uint64_t id = (ts.tv_sec % 1000000000) * 1000000000 + ts.tv_nsec;
now you are guaranteed unique thread ids systemwide.
现在,您可以保证在系统范围内拥有唯一的线程 ID。
回答by 6502
Another alternative:
另一种选择:
#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;
}
The generated code for this function by g++ in x86 64-bit is just:
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
I.e. a single branch without any synchronization that will be correctly predicted except for the first time you call the function. After that just a single memory access without synchronization.
即没有任何同步的单个分支将被正确预测,除非您第一次调用该函数。之后只是一个没有同步的内存访问。
回答by geh
Maybe this solution be helpful to someone. Call it a first time im main()
. Warning: names
grows indefinitely.
也许这个解决方案对某人有帮助。第一次打电话给我main()
。警告:names
无限增长。
std::string currentThreadName(){
static std::unordered_map<std::thread::id,std::string> names;
static std::mutex mtx;
std::unique_lock<std::mutex> lock(mtx);
auto id = std::this_thread::get_id();
if(names.empty()){
names[id] = "Thread-main";
} else if(names.find(id) == names.end()){
std::stringstream stream;
stream << "Thread-" << names.size();
names[id] = stream.str();
}
return names[id];
}