検索したが、満足のいく答えに出会わないでください。
Pthread_tを印刷する移植可能な方法はないことを知っています。
アプリでどのように実行しますか?
更新:
実際には、pthread_tは必要ありませんが、デバッグメッセージで異なるスレッドを識別する小さな数値IDが必要です。
私のシステム(64ビットRHEL 5.3)では、unsigned long intとして定義されているため、大きな数字であり、印刷するだけでデバッグ行の貴重な場所を占めています。 gdb assign short tidsはどうですか?
これは、実際に何であるかに関係なく、pthread_t
の16進表現を出力します。
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
の小さなIDを出力するには、次のようなものを使用できます(今回はiostreamを使用)。
void printPt(std::ostream &strm, pthread_t pt) {
static int nextindex = 0;
static std::map<pthread_t, int> ids;
if (ids.find(pt) == ids.end()) {
ids[pt] = nextindex++;
}
strm << ids[pt];
}
プラットフォームとpthread_t
の実際の表現によっては、operator<
に要素の順序付けが必要なため、pthread_t
のstd::map
を定義する必要がある場合があります。
bool operator<(const pthread_t &left, const pthread_t &right) {
...
}
GDBは、Linux上の短い番号にスレッドID(カーネルpid、別名LWP)を使用します。試してください:
#include <syscall.h>
...
printf("tid = %d\n", syscall(SYS_gettid));
この場合、 POSIX標準ではpthread_t
が算術型である必要がなくなりました であるため、オペレーティングシステムによって異なります。
IEEE Std 1003.1-2001/Cor 2-2004、アイテムXBD/TC2/D6/26が適用され、算術型である必要のない型のリストに
pthread_t
が追加され、したがってpthread_t
構造体として定義されます。
sys/types.h
ヘッダーを見て、pthread_t
がどのように実装されているかを確認する必要があります。それからあなたはそれがあなたが合うと思う方法でそれを印刷することができます。これを行うための移植可能な方法はなく、使用しているオペレーティングシステムを言うこともないため、これ以上言うことはありません。
Edit:新しい質問に答える GDBは新しいスレッドが開始するたびに独自のスレッドIDを割り当てます :
デバッグのために、gdbは独自のスレッド番号(常に1つの整数)をプログラムの各スレッドに関連付けます。
各スレッド内で一意の番号を印刷する場合、最もクリーンなオプションは、おそらく、起動時に使用する番号を各スレッドに伝えることです。
OK、これが私の最終的な答えのようです。 2つの実際の問題があります。
1。POSIX ID(pthread_t)を出力
Pthread_tは、バイトごとに16進数が印刷されたバイトの配列として単純に処理できます。そのため、固定サイズのタイプに制限されません。唯一の問題はバイトオーダーです。印刷されたバイトの順序が、単純な「int」印刷の場合と同じであるなら、おそらく好きでしょう。以下はリトルエンディアンの例であり、ビッグエンディアンの場合のみ順序を元に戻す必要があります(定義の下で)。
#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。印刷可能なスレッドIDを短くする
提案されたケースのいずれにおいても、実際のスレッドID(posix)を何らかのテーブルのインデックスに変換する必要があります。ただし、大きく異なる2つのアプローチがあります。
2.1。スレッドを追跡します。
テーブル内のすべての既存スレッドのスレッドIDを追跡し(pthread_create()呼び出しをラップする必要があります)、実際のスレッドIDではなくテーブルインデックスのみを取得する「オーバーロード」id関数を使用できます。このスキームは、リソース追跡の内部スレッド関連のデバッグにも非常に役立ちます。明らかな利点は、将来の拡張が可能なスレッドレベルのトレース/デバッグ機能の副作用です。欠点は、スレッドの作成/破壊を追跡するための要件です。
部分的な擬似コードの例を次に示します。
pthread_create_wrapper(...)
{
id = pthread_create(...)
add_thread(id);
}
pthread_destruction_wrapper()
{
/* Main problem is it should be called.
pthread_cleanup_*() calls are possible solution. */
remove_thread(pthread_self());
}
unsigned thread_id(pthread_t known_pthread_id)
{
return seatch_thread_index(known_pthread_id);
}
/* user code */
printf("04x", thread_id(pthread_self()));
2.2。新しいスレッドIDを登録するだけです。
ロギング中にpthread_self()を呼び出し、スレッドを知っている場合は内部テーブルを検索します。そのようなIDのスレッドが作成された場合、そのインデックスが使用されます(または以前のスレッドから再利用されます。実際には同じ瞬間に同じIDが2つないので問題ありません)。スレッドIDがまだわかっていない場合は、新しいインデックスが生成/使用されるように新しいエントリが作成されます。
利点は単純さです。欠点は、スレッドの作成/破壊の追跡ではありません。そのため、これを追跡するには、外部のメカニズムが必要です。
Centos 5.4 x86_64では、pthread_tはunsigned longの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 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;
}
これには、関数呼び出しでthread_idを渡す必要がないという利点がありますが、機能しません。 Mac OSで。
pthread_tが単なる数字の場合;これが最も簡単です。
int get_tid(pthread_t tid)
{
assert_fatal(sizeof(int) >= sizeof(pthread_t));
int * threadid = (int *) (void *) &tid;
return *threadid;
}
ルックアップテーブル(pthread_t : int)
は、多数の短命スレッドを開始するプログラムでメモリリークになる可能性があります。
pthread_t
のバイトのハッシュを作成する(構造体、ポインター、長整数型など)のは、ルックアップテーブルを必要としない便利なソリューションです。他のハッシュと同様に衝突のリスクがありますが、要件に合わせてハッシュの長さを調整できます。
このスレッドは非常に古いものです。上記のすべての投稿を読んだので、これをきちんとした方法で処理するためにもう1つのアイデアを追加したいと思います:とにかくマッピングビジネスに入る(pthread_toをintにマッピングする)場合は、読みやすさをさらに一歩進めることもできます。 pthread_create_wrapperを作成して、文字列も受け取るようにします...スレッドの名前。私は、WindowsおよびWindows CEのこの「SetThreadName()」機能に感謝することを学びました。利点:IDは単なる数字ではなく、どのスレッドがどの目的を持っているかがわかります。
それを符号なしのshortに変換してから、最後の4桁の16進数だけを印刷してみてください。結果の値は、ニーズに対して十分に一意である場合があります。
ジェームズが前述したように、最良の方法は、タイプが定義されているヘッダーを調べることです。
pthread_tの定義はpthreadtypes.hで見つけることができます:
/usr/include/bits/pthreadtypes.h
最初の投稿の補足:ユーザー定義のユニオン型を使用してpthread_tを保存します。
union tid {
pthread_t pthread_id;
unsigned long converted_id;
};
印刷したいときはいつでもpthread_t
、tid
を作成し、tid.pthread_id = ...
、次に印刷tid.converted_id
。