web-dev-qa-db-ja.com

C ++ 11で整数スレッドIDを取得する方法

c ++ 11は現在のスレッドIDを取得する可能性がありますが、整数型にキャストできません:

cout<<std::this_thread::get_id()<<endl;

出力:139918771783456

cout<<(uint64_t)std::this_thread::get_id()<<endl;

エラー:タイプ「std :: thread :: id」からの無効なキャストは「uint64_t」を入力します他のタイプと同じ:タイプ「std :: thread :: id」からの無効なキャストは「uint32_t」を入力します

整数スレッドIDを取得するために、ポインターキャストを実行したくありません。それを行うための何らかの合理的な方法(私はそれが移植可能になりたいので標準です)はありますか?

73
NoSenseEtAl

移植可能なソリューションは、生成された独自のIDをスレッドに渡すことです。

int id = 0;
for(auto& work_item : all_work) {
    std::async(std::launch::async, [id,&work_item]{ work_item(id); });
    ++id;
}

std::thread::idタイプは、比較にのみ使用され、算術には使用されません(つまり、缶に書かれているようにidentifier)。 operator<<によって生成されるテキスト表現でさえ未指定であるため、数値の表現であることに頼ることはできません。

独自のIDにstd::thread::id値のマップを使用し、IDを直接渡すのではなく、スレッド間で(適切な同期を使用して)このマップを共有することもできます。

28

あなたはただする必要があります

std::hash<std::thread::id>{}(std::this_thread::get_id())

size_tを取得します。

cppreference から:

std::hashクラスのstd::thread::idのテンプレート特化により、ユーザーはスレッドの識別子のハッシュを取得できます。

72
888

別のID(アイデア?^^)は、文字列ストリームを使用することです。

std::stringstream ss;
ss << std::this_thread::get_id();
uint64_t id = std::stoull(ss.str());

そして、物事がうまくいかない場合に例外が必要ない場合は、try catchを使用してください...

22
Mike

1つのアイデアは、スレッドローカルストレージを使用して変数を格納することです(スレッドローカルストレージの規則に準拠している限り、どのタイプでもかまいません)。次に、その変数のアドレスを「スレッドID」として使用します。明らかに、算術演算は意味がありませんが、整数型になります。

後世の場合:pthread_self()は_pid_t_を返し、posixです。これは、ポータブルの定義のためにポータブルです。

gettid()、ほぼ確実に移植性はありませんが、GDBフレンドリーな値を返します。

6
tgoodhart

私はこれがどれほど速いか本当に知りませんが、これは私がゲスト化することに成功した解決策です:

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;

繰り返しますが、構造体へのポインタを取得し、それを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 :)書き換えは、この種のバグを見つけるよりも簡単です。 :)

4
NoSenseEtAl

thread::native_handle()thread::native_handle_typeのtypedefであるlong unsigned intを返します。

スレッドがデフォルトで構成されている場合、native_handle()は0を返します。OSスレッドが接続されている場合、戻り値はゼロ以外です(POSIXではpthread_tです)。

3
Alexey Polonsky

thread_idの使用目的によって異なります。使用できます:

std::stringstream ss;
ss << std::this_thread::get_id();
uint64_t id = std::stoull(ss.str());

これにより、処理時に一意の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;

これで、システム全体で一意のスレッドIDが保証されます。

2
Pandrei

このようにして、動作するはずです:

std::stringstream ss;
ss << std::this_thread::get_id();
int id = std::stoi(ss.str());

ライブラリsstreamを含めることを忘れないでください

2
Federico Rizzo

このソリューションは誰かに役立つかもしれません。初めてim 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];
}
1
geh

Thread :: get_id()を使用しない主な理由は、単一のプログラム/プロセスで一意ではないためです。これは、最初のスレッドが終了すると、idを2番目のスレッドに再利用できるためです。

これは恐ろしい機能のように見えますが、c ++ 11の機能です。

0
midjji