108 votes

Comment obtenir l'identifiant d'un thread entier en c++11

C++11 a la possibilité d'obtenir l'identifiant du thread en cours, mais il ne peut être converti en un entier :

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

sortie : 139918771783456

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

error : invalid cast from type 'std::thread::id' to type 'uint64_t' idem pour les autres types : invalid cast from type 'std::thread::id' to type 'uint32_t'

Je ne veux vraiment pas faire de casting de pointeur pour obtenir l'identifiant entier du thread. Il y a t-il un moyen raisonnable (standard parce que je veux que ce soit portable) de le faire ?

5voto

NoSenseEtAl Points 2342

Je ne sais pas vraiment quelle est la rapidité de cette solution, mais c'est la solution que j'ai réussi à estimer :

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;

Encore une fois, je commence à penser qu'obtenir un pointeur sur la structure et le convertir en unsigned int ou uint64_t est la solution... EDIT :

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 pour éviter des problèmes infernaux :) La réécriture est facile comparée à la chasse à ce genre de bug :)

5voto

Federico Rizzo Points 80

C'est ainsi qu'il devrait fonctionner :

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

N'oubliez pas d'inclure la bibliothèque sstream

5voto

6502 Points 42700

Une autre 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;
}

Le code généré pour cette fonction par g++ en x86 64 bits est juste :

_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

C'est-à-dire une branche unique sans aucune synchronisation qui sera correctement prédite sauf la première fois que vous appelez la fonction. Après cela, il ne s'agit que d'un accès unique à la mémoire sans synchronisation.

4voto

Alexey Polonsky Points 432

thread::native_handle() retours thread::native_handle_type qui est un typedef de long unsigned int .

Si le thread est construit par défaut, native_handle() renvoie 0. Si un thread du système d'exploitation y est attaché, la valeur de retour est non nulle (c'est pthread_t sous POSIX).

2voto

Pandrei Points 1751

Cela dépend de l'usage que vous voulez faire de l'identifiant de la discussion (thread_id) ; vous pouvez utiliser :

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

Cela générera un identifiant unique au sein de votre processus ; mais il y a une limitation : si vous lancez plusieurs instances du même processus et que chacune d'entre elles écrit son identifiant de thread dans un fichier commun, l'unicité de l'identifiant de thread n'est pas garantie ; en fait, il est très probable qu'il y ait des chevauchements. Dans ce cas, vous pouvez faire quelque chose comme :

#include <sys/time.h>
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
uint64_t id = (ts.tv_sec % 1000000000) * 1000000000 + ts.tv_nsec;

vous avez désormais la garantie d'avoir des identifiants uniques dans tout le système.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X