获取PostThreadMessage的boost :: thread的ID

我有一个使用Boost 1.47.0的Visual Studio 2008 C ++项目,我需要将boost :: thread的本地Windows ID传递给PostThreadMessage。

在Windows Vista和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

这是一个聪明/讨厌的黑客使用Johannes 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; } 

我不确定这是否符合获得信息的“好方法”。 但是,它的工作原理不需要修改boost头文件或库文件,编译器也不会抱怨 – 即使是相对较高的警告。 测试:

  • MinGW 4.6.1 -Wall -Wextra关闭了一些特别嘈杂的警告 – 但不是特别针对此测试。 他们在我的通用“编译这个测试”脚本中被关闭。
  • VC ++ 2008和2010与/ W4

这里有一个示例运行,显示它的工作原理

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

当然,不用说,如果boost :: thread随时间变化,这可能会中断,但可能不会默默地。


一些解释性说明/指针:

这个技术中使用的“漏洞”是C ++ 03 14.7.2 / 8“显式实例化”:

通常的访问检查规则不适用于用来指定显式实例的名称。 [注意:特别是函数声明符中使用的模板参数和名称(包括参数类型,返回类型和异常说明)可以是私有类型或对象,这些类型或对象通常是不可访问的,模板可以是成员模板或成员函数这通常是不可访问的。]

戴夫·亚伯拉罕(Dave Abrahams)有一个“主旨”,它使用了类似的技巧和评论,很好地解释了发生了什么事情:

我发现他在评论中留下了一篇关于私人会员访问的文章: 访问私人会员。 这很容易!