Как получить целочисленный идентификатор потока в C ++ 11 - PullRequest
72 голосов
/ 15 сентября 2011

c ++ 11 имеет возможность получить идентификатор текущего потока, но его нельзя преобразовать в целочисленный тип:

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»

Я действительно не хочу делать указатель, чтобы получить целочисленный идентификатор потока. Есть ли какой-то разумный способ (стандартный, потому что я хочу, чтобы он был переносимым) сделать это?

Ответы [ 9 ]

72 голосов
/ 04 апреля 2013

Вам просто нужно сделать

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

чтобы получить size_t.

От cppreference :

Специализация шаблона std::hash для класса std::thread::id позволяет пользователям получать хэши идентификаторов потоков.

27 голосов
/ 15 сентября 2011

Переносимое решение заключается в передаче собственных сгенерированных идентификаторов в поток.

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

Тип std::thread::id должен использоваться только для сравнения, а не для арифметики (то есть, как сказано в банке: идентификатор ).Даже его текстовое представление, создаваемое operator<<, равно неопределено , поэтому нельзя полагаться на то, что оно является представлением числа.

Вы также можете использовать карту значений std::thread::idна свой собственный идентификатор и поделитесь этой картой (с правильной синхронизацией) среди потоков, вместо прямой передачи идентификатора.

22 голосов
/ 28 мая 2014

Другой идентификатор (идея? ^^) будет использовать строковые потоки:

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

И используйте try catch, если вы не хотите исключения в случае, если что-то пойдет не так ...

6 голосов
/ 09 декабря 2011

Одна идея состоит в том, чтобы использовать локальное хранилище потока для хранения переменной - не имеет значения, какой тип, при условии, что он соответствует правилам локального хранилища потока, - затем использовать адрес этой переменной в качестве «идентификатора потока». ». Очевидно, что любая арифметика не будет иметь смысла, но это будет целочисленный тип.

для потомков: pthread_self() возвращает pid_t и является posix. Это портативный для некоторого определения портативного.

gettid(), почти наверняка не переносимый, но он возвращает дружественное значение GDB.

4 голосов
/ 15 сентября 2011

Я действительно не знаю, насколько это быстро, но это решение, которое мне удалось угадать:

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;

Опять я начинаю думать, что получаю указатель на структуру и приводим ее к unsignedint или uint64_t - это ответ ... 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 для предотвращения адских проблем :) Переписать легко по сравнению с поиском такого рода ошибки.:)

3 голосов
/ 03 января 2018

thread::native_handle() возвращает thread::native_handle_type, который является typedef для long unsigned int.

Если поток создан по умолчанию, native_handle () возвращает 0. Если к нему присоединен поток ОС, возвращаемое значение ненулевое (это pthread_t в POSIX).

2 голосов
/ 07 сентября 2017

Таким образом, должно работать:

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

Не забудьте включить библиотеку sstream

2 голосов
/ 27 июля 2017

это зависит от того, для чего вы хотите использовать thread_id; Вы можете использовать:

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

Это создаст уникальный идентификатор внутри вашего процесса; но есть ограничение: если вы запускаете несколько экземпляров одного и того же процесса и каждый из них записывает свои идентификаторы потоков в общий файл, уникальность thread_id не гарантируется; на самом деле очень вероятно, что у вас будут совпадения. В этом случае вы можете сделать что-то вроде:

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

теперь вам гарантированы уникальные идентификаторы потоков для всей системы.

1 голос
/ 19 апреля 2019

Может быть, это решение кому-нибудь пригодится.Назовите это впервые 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];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...