我有一个使用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:thread将线程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
有获得身份证的好方法吗?看到我需要的数据非常令人沮丧,但却无法实现。
谢谢, PaulH
答案 0 :(得分: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头或库的情况下工作,并且编译器根本不会抱怨 - 即使警告相对较高。经过测试:
-Wall -Wextra
关闭了一些特别嘈杂的警告 - 但不是特别针对此测试。它们在我的通用“编译本测试”脚本中被关闭。这是一个显示它的示例运行:
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有一个'gist',它使用类似的技巧和评论,很好地解释了正在发生的事情:
我发现在评论中他留下了关于私人会员访问的文章,关于约翰内斯的博客:Access to private members. That's easy!