【问题标题】:Getting the ID of a boost::thread for PostThreadMessage获取 PostThreadMessage 的 boost::thread 的 ID
【发布时间】:2012-02-27 22:57:27
【问题描述】:

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

在 Windows Vista 和 7 中,我会这样做:

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

这很好,但我还需要我的应用在不存在GetThreadId 的 XP 中工作。

我发现 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

有没有什么好的方法来获取ID?看到我需要的数据,却无法获取,非常令人沮丧。

谢谢, 保罗H

【问题讨论】:

    标签: c++ windows boost boost-thread


    【解决方案1】:

    这是使用Johannes Schaub - litb 在他的博客Access to private members: Safer nastiness 上描述的技术的聪明/讨厌的hack。所有的功劳都应该归功于约翰内斯。我会承担将其应用于现实世界场景的责任(或者也许你可以):

    #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 有一个“要点”,它使用类似的技术和 cmets 很好地解释了正在发生的事情:

    我发现他在 Johannes 博客上一篇关于私人会员访问的文章留下的评论中:Access to private members. That's easy!

    【讨论】:

    • 这是我今天看到的最酷的东西。我会浪费接下来的 3 个小时试图理解它。谢谢!
    猜你喜欢
    • 2020-06-22
    • 1970-01-01
    • 2014-09-29
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多