programing tip

C ++ 11에서 정수 스레드 ID를 얻는 방법

itbloger 2020. 10. 19. 07:47
반응형

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를 얻기 위해 포인터 캐스팅을 정말로 원하지 않습니다. 그것을하기위한 합리적인 방법 (휴대용이되기를 원하기 때문에 표준)이 있습니까?


이식 가능한 솔루션은 자신이 생성 한 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유형은 비교에 사용되는 경우에만,하지 (즉,이 캔에 말한대로 : 산술에 대한 식별자 ). 생산에도 해당 텍스트 표현 operator<<입니다 지정되지 않은 당신이 숫자의 표현 인에 의존하지 수 있습니다.

또한 std::thread::id자신의 ID에 대한 값 맵을 사용 하고 ID를 직접 전달하는 대신 스레드간에 적절한 동기화를 통해이 맵을 공유 할 수 있습니다.


당신은 할 필요가 있습니다

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

를 얻을 수 있습니다 size_t.

에서 cppreference :

클래스 std::hash대한 템플릿 전문화를 std::thread::id통해 사용자는 스레드 식별자의 해시를 얻을 수 있습니다.


또 다른 ID (아이디어? ^^)는 stringstreams를 사용하는 것입니다.

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

일이 잘못되는 경우 예외를 원하지 않으면 try catch를 사용하십시오.


한 가지 아이디어는 스레드 로컬 저장소를 사용하여 변수를 저장하는 것입니다.-스레드 로컬 저장소의 규칙을 준수하는 한 어떤 유형이든 상관없이 해당 변수의 주소를 "스레드 ID"로 사용합니다. 분명히 arithemetic은 의미가 없지만 통합 유형이 될 것입니다.

후손의 경우 : pthread_self()a를 반환하고 pid_tposix입니다. 이것은 휴대용의 일부 정의를 위해 이식 가능합니다.

gettid(), 거의 확실하게 이식 할 수 없지만 GDB 친화적 인 값을 반환합니다.


나는 이것이 얼마나 빠른지 정말로 모른다. 그러나 이것이 내가 게스트화할 수 있었던 해결책이다.

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 :) 재 작성은 이런 종류의 버그를 찾는 것에 비해 쉽습니다. :)


이런 식으로 작동해야합니다.

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

라이브러리 sstream을 포함하는 것을 잊지 마십시오


thread::native_handle()thread::native_handle_type대한 typedef 인을 반환 합니다 long unsigned int.

thread가 기본 생성 된 경우 native_handle ()은 0을 반환합니다. 연결된 OS 스레드가있는 경우 반환 값은 0이 아닙니다 (POSIX의 경우 pthread_t).


그것은 당신이 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가 보장됩니다.


Maybe this solution be helpful to someone. Call it a first time im main(). Warning: names grows indefinitely.

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];
}

Another 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;
}

The generated code for this function by g++ in x86 64-bit is just:

_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

I.e. a single branch without any synchronization that will be correctly predicted except for the first time you call the function. After that just a single memory access without synchronization.


A key reason not to use thread::get_id() is that it isn't unique for in a single program/process. This is because the id can be reused for a second thread, once the first thread finishes.

This seems like a horrible feature, but its whats in c++11.

참고URL : https://stackoverflow.com/questions/7432100/how-to-get-integer-thread-id-in-c11

반응형