2012-02-27 29 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

相关问题