2012-02-27 6 views
5

私は、PostThreadMessageに渡すためにboost :: threadのネイティブWindows IDを取得する必要があるBoost 1.47.0を使用するVisual Studio 2008 C++プロジェクトを持っています。PostThreadMessageのboost :: threadのIDを取得する

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

これは素晴らしいですが、GetThreadIdが存在しない場合、私はまた、XPで動作するように私のアプリを必要とする:

Windows Vistaの場合

と7、私はこれを行うだろう。

私はboost:threadがboost :: thread :: idのプライベートデータメンバーthread_dataにスレッドID値を格納していることを発見しました。私は一時的なboost::thread::idオブジェクトを参照するためのコンパイラの警告を取得を開始、

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

しかし:私はいくつかの厄介なキャストを行うことによって、それに得ることができます。

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

IDを取得するには良い方法はありますか?私が必要とするデータを見るのは非常にイライラしますが、それを得ることはできません。

おかげで、

答えて

6

PaulHは、ここで彼のブログ、Access to private members: Safer nastinessJohannes Schaub - litbによって記載された技術を使用して賢い/厄介なハックです。すべてのクレジットはヨハネスに行きます。私は、実際のシナリオにそれを適用するための責任を取るだろう(または多分あなたは缶):

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

私は、これは情報を取得するために「良い方法」としての資格かはわかりません。しかし、それはブーストヘッダやライブラリを変更することなく動作し、コンパイラは比較的高い警告があっても全く文句を言うことはありません。上でテスト: - 具体的には、この試験のためにではなく、いくつかの特にうるさい警告を

  • MinGWの4.6.1 -Wall -Wextraはオフ。それらは私の一般的な「このテストをコンパイルする」スクリプトではオフになっています。
  • /W4
  • とVC++ 2008と2010

ここでそれが動作を示すサンプルの実行:もちろん

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

+0

+1です。 – PaulH

関連する問題