C++ 如何打印pthread\u t

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

搜索,但没有找到令人满意的答案

我知道没有可移植的方式来打印pthread\u t

你如何在你的应用程序中做到这一点

更新:

实际上,我不需要pthread\u t,而是需要一些小的数字id,在调试消息中标识不同的线程


在我的系统(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);