简体   繁体   English

获取PostThreadMessage的boost :: thread的ID

[英]Getting the ID of a boost::thread for PostThreadMessage

I have a Visual Studio 2008 C++ project using Boost 1.47.0 where I need to get the native Windows ID of a boost::thread to pass to PostThreadMessage. 我有一个使用Boost 1.47.0的Visual Studio 2008 C ++项目,我需要获取boost :: thread的本地Windows ID传递给PostThreadMessage。

In Windows Vista and 7, I would just do this: 在Windows Vista和7中,我只需要这样做:

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

This is fine, but I also need my app to work in XP where GetThreadId does not exist. 很好,但是我还需要我的应用程序在不存在GetThreadId XP中工作。

I have found that boost:thread stores the thread ID value in boost::thread::id's private data member thread_data . 我发现boost:thread将线程ID值存储在boost :: thread :: id的私有数据成员thread_data I can get to that by doing some nasty casts: 我可以通过一些讨厌的演员来解决这个问题:

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

But, I start getting compiler warnings for referencing a temporary boost::thread::id object. 但是,我开始收到引用临时boost::thread::id对象的编译器警告。

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

Is there a good way to get the ID? 是否有获取ID的好方法? It is very frustrating to see the piece of data I need, but not be able to get at it. 看到我需要但无法获取的数据非常令人沮丧。

Thanks, PaulH 谢谢PaulH

Here's a clever/nasty hack using a technique described by Johannes Schaub - litb on his blog, Access to private members: Safer nastiness . 这是Johannes Schaub-litb在他的博客“ 访问私有成员:更安全的恶意行为”中描述的一种巧妙/讨厌的技术。 All credit should go to Johannes. 所有功劳应归功于约翰内斯。 I'll take the blame for applying it to a real-world scenario (or maybe you can): 我会责怪将其应用到现实世界中(或者也许可以):

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

I'm not sure if this qualifies as a "good way" to get the info. 我不确定这是否符合获取信息的“好方法”。 But it works without modifying the boost headers or libraries, and the compiler doesn't complain at all - even with relatively high warnings. 但是它无需修改boost头文件或库就可以工作,并且即使有相对较高的警告,编译器也不会抱怨。 Tested on: 经过测试:

  • MinGW 4.6.1 -Wall -Wextra with a few especially noisy warnings turned off - but not for this test in particular. MinGW 4.6.1 -Wall -Wextra ,带有一些特别嘈杂的警告已关闭-但这不是特别针对此测试。 They're turned off in my generic 'compile this test' script. 在我的通用“编译此测试”脚本中将其关闭。
  • VC++ 2008 and 2010 with /W4 带有/ W4的VC ++ 2008和2010

Here a sample run that shows it works: 这里有一个示例运行,显示了它的工作原理:

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

Of course, it should go without saying that this might break if/when boost::thread changes over time, but probably not silently. 当然,如果boost :: thread随时间变化,这可能会中断,但是可能不会默默地中断。


Some explanatory notes/pointers: 一些说明性注释/指针:

The 'loophole' used in this technique is in C++03 14.7.2/8 "Explicit instantiation": 此技术中使用的“漏洞”在C ++ 03 14.7.2 / 8“显式实例化”中:

The usual access checking rules do not apply to names used to specify explicit instantiations. 通常的访问检查规则不适用于用于指定显式实例化的名称。 [Note: In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) may be private types or objects which would normally not be accessible and the template may be a member template or member function which would not normally be accessible.] [注:特别是,函数声明符中使用的模板参数和名称(包括参数类型,返回类型和异常规范)可能是私有类型或对象,通常是无法访问的,并且模板可能是成员模板或成员函数通常无法访问。]

Dave Abrahams has a 'gist' that uses similar techniques along with comments that explain pretty nicely what's going on: 戴夫·亚伯拉罕(Dave Abrahams)有一个“要点”,他使用类似的技术以及可以很好地解释正在发生的事情的评论:

I found that in a comment he left on a previous article about private member access on Johannes' blog: Access to private members. 我发现他在Johannes博客上有关私人会员访问的上一篇文章的评论中留下了评论: 私人会员的访问。 That's easy! 这很简单!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM