获取PostThreadMessage的boost :: thread的ID

时间:2012-02-27 22:57:28

标签: c++ windows boost boost-thread

我有一个使用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

1 个答案:

答案 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头或库的情况下工作,并且编译器根本不会抱怨 - 即使警告相对较高。经过测试:

  • MinGW 4.6.1 -Wall -Wextra关闭了一些特别嘈杂的警告 - 但不是特别针对此测试。它们在我的通用“编译本测试”脚本中被关闭。
  • VC ++ 2008和2010 with / 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有一个'gist',它使用类似的技巧和评论,很好地解释了正在发生的事情:

我发现在评论中他留下了关于私人会员访问的文章,关于约翰内斯的博客:Access to private members. That's easy!