c ++ 11 a la possibilité d'obtenir l'id du thread actuel, mais il n'est pas convertible en type entier:
cout<<std::this_thread::get_id()<<endl;
sortie: 139918771783456
cout<<(uint64_t)std::this_thread::get_id()<<endl;
erreur: conversion invalide du type 'std :: thread :: id' au type 'uint64_t' identique pour les autres types: conversion invalide du type 'std :: thread :: id' au type 'uint32_t'
Je ne veux vraiment pas faire de casting de pointeur pour obtenir l'identifiant de thread entier. Existe-t-il un moyen raisonnable (standard parce que je veux que ce soit portable) pour le faire?
La solution portable consiste à transmettre vos propres identifiants générés au thread.
int id = 0;
for(auto& work_item : all_work) {
std::async(std::launch::async, [id,&work_item]{ work_item(id); });
++id;
}
Le std::thread::id
type ne doit être utilisé que pour des comparaisons, pas pour l’arithmétique (c’est-à-dire comme il est dit sur la boîte: un identifiant). Même sa représentation textuelle produite par operator<<
est non spécifié, vous ne pouvez donc pas vous fier à la représentation d'un nombre.
Vous pouvez aussi utiliser une carte de std::thread::id
valeurs à votre propre identifiant, et partager cette carte (avec une synchronisation correcte) entre les threads, au lieu de transmettre l'identifiant directement.
Vous avez juste besoin de faire
std::hash<std::thread::id>{}(std::this_thread::get_id())
pour obtenir un size_t
.
De cppreference :
La spécialisation de template de
std::hash
pour lestd::thread::id
class permet aux utilisateurs d’obtenir des hachages des identifiants de threads.
Une autre id (idée? ^^) serait d’utiliser stringstreams:
std::stringstream ss;
ss << std::this_thread::get_id();
uint64_t id = std::stoull(ss.str());
Et utilisez try catch si vous ne voulez pas d'exception si les choses tournent mal ...
Une idée serait d'utiliser le stockage local de threads pour stocker une variable - peu importe le type, dans la mesure où elle respecte les règles de stockage local de thread - d'utiliser l'adresse de cette variable comme "identifiant de thread". Évidemment, tout calcul ne sera pas significatif, mais ce sera un type intégral.
Pour la postérité: pthread_self()
renvoie un pid_t
Et est posix. Ceci est portable pour une certaine définition de portable.
gettid()
, presque certainement pas portable, mais renvoie une valeur conviviale GDB.
Je ne sais vraiment pas à quelle vitesse ça va, mais c'est la solution que j'ai réussi à faire avec guestimate:
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 réponse ... 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 les problèmes infernaux :) La réécriture est facile comparée à la traque de ce type de bogue. :)
thread::native_handle()
retourne thread::native_handle_type
, qui est un typedef à long unsigned int
.
Si thread est construit par défaut, native_handle () renvoie 0. Si un thread de système d'exploitation y est associé, la valeur renvoyée est différente de zéro (il s'agit de pthread_t sur POSIX).
cela dépend de ce que vous voulez utiliser le thread_id pour; 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 avec votre processus; mais il y a une limite: si vous lancez plusieurs instances du même processus et que chacune d'elles écrit leurs identifiants de thread dans un fichier commun, l'unicité du thread_id n'est pas garantie; en fait, il y a de fortes chances que vous ayez 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;
maintenant, vous avez la garantie d'un identifiant de thread unique dans tout le système.
De cette façon, 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
Peut-être que cette solution pourrait être utile à quelqu'un. Appelez-le une première fois im main()
. Attention: names
croît indéfiniment.
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];
}
Une des principales raisons de ne pas utiliser thread :: get_id () est qu'il n'est pas unique dans un seul programme/processus. Cela est dû au fait que l'identifiant peut être réutilisé pour un deuxième thread, une fois le premier thread terminé.
Cela semble être une caractéristique horrible, mais c’est sa version c ++ 11.