C++ 如何打印pthread\u t
搜索,但没有找到令人满意的答案 我知道没有可移植的方式来打印pthread\u t 你如何在你的应用程序中做到这一点 更新: 实际上,我不需要pthread\u t,而是需要一些小的数字id,在调试消息中标识不同的线程C++ 如何打印pthread\u t,c++,c,linux,pthreads,C++,C,Linux,Pthreads,搜索,但没有找到令人满意的答案 我知道没有可移植的方式来打印pthread\u t 你如何在你的应用程序中做到这一点 更新: 实际上,我不需要pthread\u t,而是需要一些小的数字id,在调试消息中标识不同的线程 在我的系统(64位RHEL 5.3)上,它被定义为无符号长整型,所以它是一个大数字,仅仅打印它就占用了调试行中一个有价值的位置。gdb如何分配短TID?在这种情况下,它取决于操作系统,因为: IEEE Std 1003.1-2001/Cor 2-2004第XBD/TC2/D6/2
在我的系统(64位RHEL 5.3)上,它被定义为无符号长整型,所以它是一个大数字,仅仅打印它就占用了调试行中一个有价值的位置。gdb如何分配短TID?在这种情况下,它取决于操作系统,因为: IEEE Std 1003.1-2001/Cor 2-2004第XBD/TC2/D6/26项适用,将
pthread_t
添加到不要求为算术类型的类型列表中,从而允许将pthread_t
定义为结构
您需要查看sys/types.h
标题,了解pthread\u t
是如何实现的;然后你可以按你认为合适的方式打印出来。因为没有一种可移植的方法来实现这一点,而且你也没有说你使用的是什么操作系统,所以没有更多的话要说
编辑:要回答您的新问题,请执行以下操作:
出于调试目的,gdb将自己的线程编号始终与程序中的每个线程关联一个整数
如果要在每个线程内部打印一个唯一的数字,最干净的选择可能是告诉每个线程在启动时使用哪个数字。在Centos 5.4 x86_64上,pthread_t是一个无符号长字符的typedef 因此,我们可以这样做
#include <iostream>
#include <pthread.h>
int main() {
pthread_t x;
printf("%li\n", (unsigned long int) x);
std::cout << (unsigned long int) x << "\n";
}
#包括
#包括
int main(){
pthread_t x;
printf(“%li\n”,(无符号长整数)x);
std::cout这将打印出一个十六进制表示的pthread\u t
,不管它实际上是什么:
void fprintPt(FILE *f, pthread_t pt) {
unsigned char *ptc = (unsigned char*)(void*)(&pt);
fprintf(f, "0x");
for (size_t i=0; i<sizeof(pt); i++) {
fprintf(f, "%02x", (unsigned)(ptc[i]));
}
}
根据平台和pthread\t
的实际表示形式,这里可能需要定义一个操作符OK,这似乎是我的最终答案。我们有两个实际问题:
- 如何为用于日志记录的线程获取更短的唯一ID
- 无论如何,我们需要为线程打印真正的pthread\u t ID(至少只是为了链接到POSIX值)
1.打印POSIX ID(pthread\u t)
您可以简单地将pthread\u t视为每个字节打印十六进制数字的字节数组。因此,您不受某些固定大小类型的限制。唯一的问题是字节顺序。您可能喜欢打印的字节顺序是否与简单的“int”打印的字节顺序相同。以下是小尾端的示例,并且只应恢复顺序(在“定义”下)对于big endian:
#include <pthread.h>
#include <stdio.h>
void print_thread_id(pthread_t id)
{
size_t i;
for (i = sizeof(i); i; --i)
printf("%02x", *(((unsigned char*) &id) + i - 1));
}
int main()
{
pthread_t id = pthread_self();
printf("%08x\n", id);
print_thread_id(id);
return 0;
}
2.2.只需注册新的线程ID。
在日志记录期间,调用pthread_self()并搜索内部表(如果它知道线程)。
如果创建了具有此类ID的线程,则会使用其索引(或者从以前的线程重新使用,实际上这并不重要,因为在同一时刻没有两个相同的ID)。如果线程ID未知,则会创建新条目,以便生成/使用新索引
优点是简单。缺点是不跟踪线程的创建/销毁。因此,要跟踪这一点,需要一些外部机制。GDB在Linux上使用线程id(又名内核pid,又名LWP)作为短编号。请尝试:
#include <syscall.h>
...
printf("tid = %d\n", syscall(SYS_gettid));
#包括
...
printf(“tid=%d\n”,syscall(SYS\u getid));
您可以尝试将其转换为无符号短字符,然后只打印最后四个十六进制数字。结果值可能足够独特,满足您的需要。您可以执行以下操作:
int thread_counter = 0;
pthread_mutex_t thread_counter_lock = PTHREAD_MUTEX_INITIALIZER;
int new_thread_id() {
int rv;
pthread_mutex_lock(&thread_counter_lock);
rv = ++thread_counter;
pthread_mutex_unlock(&thread_counter_lock);
return rv;
}
static void *threadproc(void *data) {
int thread_id = new_thread_id();
printf("Thread %d reporting for duty!\n", thread_id);
return NULL;
}
如果您可以依赖GCC(在这种情况下,clang也起作用),那么您也可以这样做:
int thread_counter = 0;
static void *threadproc(void *data) {
int thread_id = __sync_add_and_fetch(&thread_counter, 1);
printf("Thread %d reporting for duty!\n", thread_id);
return NULL;
}
如果您的平台支持此功能,请选择类似选项:
int thread_counter = 0;
int __thread thread_id = 0;
static void *threadproc(void *data) {
thread_id = __sync_add_and_fetch(&thread_counter, 1);
printf("Thread %d reporting for duty!\n", thread_id);
return NULL;
}
这样做的好处是,您不必在函数调用中传递线程id,但在Mac OS上不起作用。如果pthread\u t只是一个数字,这将是最简单的
int get_tid(pthread_t tid)
{
assert_fatal(sizeof(int) >= sizeof(pthread_t));
int * threadid = (int *) (void *) &tid;
return *threadid;
}
查找表(pthread\u t:int)
可能会成为启动大量短期线程的程序中的内存泄漏
创建pthread\u t
的字节散列(无论是结构、指针、长整数还是其他)可能是一个不需要查找表的可用解决方案。与任何哈希一样,存在冲突的风险,但您可以调整哈希的长度以满足您的要求。我知道,此线程非常古老。阅读了所有上述帖子后,我想再添加一个想法,以简洁的方式处理此问题:
如果您仍然从事映射业务(将pthread_映射为int),那么您还可以进一步提高可读性。让您的pthread_创建_包装,使其也包含一个字符串…线程的名称。
我学会了欣赏windows和windows CE上的“SetThreadName()”功能。
优点:您的ID不仅仅是数字,您还可以看到,您的哪个线程有什么用途。只是对第一篇文章的补充:使用用户定义的联合类型来存储pthread\t:
union tid {
pthread_t pthread_id;
unsigned long converted_id;
};
每当您想要打印pthread\u t
时,创建一个tid
并分配tid.pthread\u id=…
,然后打印tid.converted\u id
,如上所述,最好的方法是查看定义类型的标题
您可以在pthreadtypes.h中找到pthread\t的定义,可在以下位置找到:
/usr/include/bits/pthreadtypes.h
无需花哨,您可以将pthread\u t
视为无需强制转换的指针:
printf("awesome worker thread id %p\n", awesome_worker_thread_id);
输出:
超级工作线程id 0x6000485e0
+1表示可移植性。但是这个解决方案产生了更长的pthread\t表示,它是数字“不可移植的”solutions.gdb分配了一个简短的数字。我很乐意使用类似的解决方案。帕特:不,它没有。请注意,ptc
指针在fprintf
行中被取消引用。在转换为无符号字符*
之前,转换为无效*
的目的是什么?为什么第一次转换不是多余的
int get_tid(pthread_t tid)
{
assert_fatal(sizeof(int) >= sizeof(pthread_t));
int * threadid = (int *) (void *) &tid;
return *threadid;
}
union tid {
pthread_t pthread_id;
unsigned long converted_id;
};
printf("awesome worker thread id %p\n", awesome_worker_thread_id);