2012-02-27 27 views
5

我有一個使用Boost 1.47.0的Visual Studio 2008 C++項目,我需要將boost :: thread的本機Windows ID傳遞給PostThreadMessage。獲取PostThreadMessage的boost :: thread的ID

在Windows Vista和Windows 7,我只是這樣做:

DWORD thread_id = ::GetThreadId(mythread.native_handle()); 

這是好的,但我也需要我的應用程序在XP中工作,其中GetThreadId不存在。

我發現boost:線程將線程ID值存儲在boost :: thread :: id的私有數據成員thread_data中。我可以做一些討厭的類型轉換得到的是:

boost::detail::thread_data_base* tdb = *reinterpret_cast< boost::detail::thread_data_base** >(&message_thread.get_id()); 
DWORD thread_id = tdb->id; 

但是,我開始收到編譯器警告,引用臨時boost::thread::id對象。

warning C4238: nonstandard extension used : class rvalue used as lvalue 

有沒有一種很好的方法來獲得ID?看到我需要的數據是非常令人沮喪的,但無法得到它。

感謝, PaulH

回答

6

下面是使用Johannes Schaub - litb在他的博客,Access to private members: Safer nastiness描述的技術巧妙的/討厭的黑客。所有的信貸都應該去約翰內斯。我要歸咎於它應用到真實世界的場景(或者你可以):

#include <windows.h> 
#include <iostream> 

#include "boost/thread.hpp" 

using namespace std; 


// technique for accessing private class members 
// 
// from: http://bloglitb.blogspot.com/2011/12/access-to-private-members-safer.html 
// 

template<typename Tag, typename Tag::type M> 
struct Rob { 
    friend typename Tag::type get(Tag) { 
    return M; 
    } 
}; 

struct thread_data_f { 
    typedef unsigned boost::detail::thread_data_base::*type; 

    friend type get(thread_data_f); 
}; 

struct thread_id_f { 
    typedef boost::detail::thread_data_ptr boost::thread::id::*type; 

    friend type get(thread_id_f); 
}; 

template struct Rob<thread_data_f, &boost::detail::thread_data_base::id>; 
template struct Rob<thread_id_f, &boost::thread::id::thread_data>; 

unsigned int get_native_thread_id(boost::thread const& t) 
{ 
    boost::detail::thread_data_ptr thread_data = t.get_id().*get(thread_id_f()); 
    unsigned thread_id = (*thread_data).*get(thread_data_f()); 

    return thread_id; 
} 

// 
// 
// 


// test of get_native_thread_id() 


void thread_func() 
{ 
    cout << "thread running..." << endl; 

    cout << "Windows says my ID is: " << GetCurrentThreadId() << endl; 

    for (;;) { 
     boost::this_thread::yield(); 
    } 
} 


int main() 
{ 
    boost::thread t(thread_func); 

    ::Sleep(2000); 

    cout << "boost says my thread ID is: " << get_native_thread_id(t) << endl; 

    return 0; 
} 

我不知道這是否有資格作爲一個「好辦法」來獲得信息。但它在不修改boost頭文件或庫的情況下工作,並且編譯器根本沒有抱怨 - 即使是相對較高的警告。測試在:

  • 的MinGW 4.6.1 -Wall -Wextra有一些特別嘈雜的警告關閉 - 但不是本次測試特別。他們在我的通用'compile this test'腳本中關閉。
  • VC++ 2008和2010/W4

這裏樣品運行,顯示它的工作原理:

C:\temp>test 
thread running... 
Windows says my ID is: 5388 
boost says my thread ID is: 5388 

當然,不用說,這可能打破,如果/當升壓::線程會隨着時間而改變,但可能不會默默地。


一些解釋性註釋/指針:

在該技術中所使用的 '漏洞' 是在C++ 03 14.7.2/8 「的顯式實例化」:

通常的訪問檢查規則不適用於用於指定 顯式實例的名稱。 [注意:特別是,函數聲明器中使用的模板參數 和名稱(包括參數類型, 返回類型和異常規範)可能是私有類型或 對象,通常這些對象通常不可訪問,模板可能是 成員模板或成員函數,通常不會是 可訪問。]

戴夫·亞伯拉罕有一個「要點」使用類似的技術與解釋非常漂亮的意見是怎麼回事沿:

我發現,在評論他離開在上一篇關於約翰內斯博客私人成員訪問的文章中:Access to private members. That's easy!

+0

這是我今天看到的最酷的事情。我會浪費接下來的3個小時試圖理解它。謝謝! – PaulH 2012-02-28 14:19:47

+0

+1爲額外的解釋性說明。 – PaulH 2012-02-29 15:15:49

相關問題