C++11线程库std::thread中提取线程id

C++有了支持多线程的thread库,只需要包含头文件#include <thread>就能使用,那么如何获取一个线程的id呢?

thread中提供了std::thread::get_id()这个方法,这个方法返回的是_M_id,类型是std::thread::id

  private:
    id              _M_id;
    thread::id
    get_id() const noexcept
    { return _M_id; }

那么这个thread::id是什么呢?这是一个在thread内部定义的类:

  /// thread
  class thread
  {
  public:
    typedef __gthread_t         native_handle_type;
    struct _Impl_base;
    typedef shared_ptr<_Impl_base>  __shared_base_type;

    /// thread::id
    class id
    {   
      native_handle_type    _M_thread;

    public:
      id() noexcept : _M_thread() { } 

      explicit
      id(native_handle_type __id) : _M_thread(__id) { } 

    private:
      friend class thread;
      friend class hash<thread::id>;

      friend bool
      operator==(thread::id __x, thread::id __y) noexcept
      { return __gthread_equal(__x._M_thread, __y._M_thread); }

      friend bool
      operator<(thread::id __x, thread::id __y) noexcept
      { return __x._M_thread < __y._M_thread; }

      template<class _CharT, class _Traits>
    friend basic_ostream<_CharT, _Traits>&
    operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id);
    }; 
  }

可以看到std::thread::id中的唯一成员变量是_M_thread,类型是native_handle_type,它是__gthread_ttypedef,这是一种gcc内置的类型,我们暂时把这个类型当unsigned long long来看待。但是这个成员变量是私有的,我们拿不出来。唯一共有的东西是它的构造函数,但是没有什么用。

幸好,它重载了<<输出运算符,这个还是std::thread::id的一个友元函数,这就好办了,用stringstream_M_thread拿到。当然你可以用std::cout直接输出。

  template<class _CharT, class _Traits>
    inline basic_ostream<_CharT, _Traits>&
    operator<<(basic_ostream<_CharT, _Traits>& __out, thread::id __id)
    {   
      if (__id == thread::id())
    return __out << "thread::id of a non-executing thread";
      else
    return __out << __id._M_thread;
    }   

以上是operator <<的具体实现,可以看到确实输出了了_M_thread

测试如下

#include <thread>

typedef unsigned long long ULL;

std::string getThreadIdOfString(const std::thread::id & id)
{
    std::stringstream sin;
    sin << id;
    return sin.str();
}

ULL getThreadIdOfULL(const std::thread::id & id)
{
    return std::stoull(getThreadIdOfString(id));
}

int main()
{
    std::thread::id id = std::this_thread::get_id();
    std::cout << "cout ----- id : " << id << std::endl;
    std::cout << "getThreadIdOfString ----- id : " << getThreadIdOfString(id) << std::endl;
    std::cout << "getThreadIdOfULL ----- id : " << getThreadIdOfULL(id) << std::endl;
    return 0;
}

这里写图片描述


其实还有更简单的方法,我们得到线程id的目的是什么,是为了标识这个线程,那么并不一定要用_M_thread。可以从上面的源码看到,class hash<thread::id>thread::id的友元类,也就是说hashstd::thread::id做了特化,因此,我们直接用hash<std::thread::id>()(id)来生成这个唯一的标识。

  // DR 889.
  /// std::hash specialization for thread::id.
  template<>
    struct hash<thread::id>
    : public __hash_base<size_t, thread::id>
    {   
      size_t
      operator()(const thread::id& __id) const noexcept
      { return std::_Hash_impl::hash(__id._M_thread); }
    };  

以上是hash<thread::id>的特化和具体实现。

测试如下

#include <bits/stdc++.h>

#include <thread>

int main()
{
    std::thread::id id = std::this_thread::get_id();
    std::cout << std::hash<std::thread::id>()(id) << std::endl;
    std::cout << "cout ----- id : " << id << std::endl;
    return 0;
}

这里写图片描述

  • 13
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值