2011-09-15 44 views
57

C++ 11獲得當前線程ID的可能性,但它不是強制轉換爲整數類型:如何獲得整數線程ID在C++ 11

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

輸出:139918771783456

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

錯誤: 從類型'的std ::螺紋:: ID爲鍵入「uint32_t的」

無效的轉換:從類型'的std ::螺紋:: ID爲鍵入「uint64_t中」 同其他類型的無效的轉換

我真的不想做指針轉換來獲得整數線程ID。有沒有合理的方法(標準,因爲我想它是便攜式)做到這一點?

+10

你需要它是一個整數?保證在它上面進行任何類型的算術都是沒有意義的,並且它在進程的上下文之外是沒有意義的,所以除了調試以外,應該不需要序列化它(這似乎是'operator <<'處理得很好)。 –

+3

這樣的事情:http://www.1024cores.net/home/lock-free-algorithms/false-sharing---faalse,而不是N = MAX_THREAD_COUNT我會有像N = 128和做thread_id%N – NoSenseEtAl

+8

如果你真的希望它是可移植的,那麼你需要做好準備,以便'thread :: id'完全不被表示爲整數。您鏈接的頁面使用由線程ID索引的數組。你有沒有考慮過使用'map '來代替?然後,您可以使用已經爲'id'類定義的關係運算符而不進行任何轉換。該標準還定義了「hash 」,因此您也可以使用無序容器。 –

回答

25

便攜式解決方案是將您自己生成的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。

+0

啊哈!但*有*文本表示!這足以讓人們在視覺上找到它們之間的區別,對吧? – Xunie

+0

這裏提到的thread :: id(或this_thread :: get_id())解決方案是最好的,因爲它不是程序員特定的。請參閱下面的Mike的串流答案以獲取字符串或整數表示形式。 – Andrew

+0

@Andrew I在答案中提到:「即使它由運算符<<產生的文本表示也沒有指定,所以你不能依賴它作爲數字的表示。看起來像「最好」這個詞的陰暗定義就在眼前。 –

4

我真的不知道有多快是這樣的,但是這是我設法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; 

再次聲明,我開始覺得讓一個指針的結構和它強制轉換爲無符號整型或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防止地獄般的問題:)改寫容易比較追捕這種錯誤。 :)

+2

您無法保證您不會使用'hash'函數獲取重複值,*如果您使用%it *,則不會獲得重複值。 –

+1

你不能用'std :: this_thread :: get_id()'得到這個保證!但你可能不需要它。多個線程彼此共享不會像每個線程與其他線程共享一樣產生相同的大量問題。像'const size_t N_COUNTERS = 128; struct Counter {std :: atomic counter; char pad [CACHE_LINE_SIZE - sizeof(原子); }計數器[N_COUNTERS];'可能沒問題。 (用於非常輕量級同步的原子或自旋鎖。) –

+0

@R。 Martinho Fernandes就像我說的,我對int值感興趣,所以我可以%它,如果它們很少,基本上是Scott所說的,碰撞是可以的。 – NoSenseEtAl

6

一個想法是使用線程本地存儲來存儲變量 - 什麼類型無關緊要,只要它符合線程本地存儲的規則 - 然後使用該變量的地址作爲您的「線程ID」。很明顯,任何一個arithemetic都不會有意義,但它將是一個完整的類型。

後人: pthread_self()返回pid_t並且是posix。這對便攜式的一些定義是便攜式的。

gettid(),幾乎肯定不是可移植的,但它確實返回了GDB友好值。

+0

'pthread_self()'實際上返回一個'pthread_t',它是不透明的(不像'pid_t'(由'gettid()'返回),它同時也是平臺特定的,至少是一個整數。但第一個+1,它解決了我的問題! – Cameron

53

您需要做的僅僅

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

獲得size_t

cppreference

The template specialization of std::hash for the std::thread::id class allows users to obtain hashes of the identifiers of threads.

+32

我認爲這必須是'std :: hash ()(std :: this_thread :: get_id())',不是嗎? – Barry

+10

哈希值是否保證是唯一的?可能不會,它將其用作唯一的線程標識符。 –

+0

邁克爾Goldshteyn它不是,但從評論很顯然,我的用法是有點具體... – NoSenseEtAl

20

另一個ID(想法?^^)是使用stringstreams:

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

與應用嘗試捕捉如果你不想在事情出錯的情況下例外...

+1

很好的答案。這一般可以達到目的。 – iammilind

+0

節省時間,我想... – kaitian521

+3

這不是可移植的,因爲不能保證'std :: thread :: id'打印爲組成一個整數的字符,其方式與保證不會保證線程ID在內部由一個整數表示。 – blubberdiblub

2

這取決於你想要的東西什麼使用thread_id作爲; 你可以使用:

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

這將生成一個唯一的ID withing您處理;但有一個限制:如果啓動同一進程的多個實例,並且每個實例都將它們的線程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系統範圍。

+0

重載的'operator <<'可以打印任何*,假定它總是打印一個整數是錯誤的。 – rustyx

2

這樣,應該工作:

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

請記住,包括圖書館sstream

+0

不錯,但爲什麼你認爲它是一個整數?它可以是十六進制或其他任何東西。 – rustyx

2

thread::native_handle()回報thread::native_handle_type,這是一個typedef到long unsigned int

如果線程是默認構造的,native_handle()返回0. 如果有一個操作系統線程連接到它,返回值是非零值(它是POSIX上的pthread_t)。