【问题标题】:C++11 'native_handle' is not a member of 'std::this_thread'C++11 'native_handle' 不是 'std::this_thread' 的成员
【发布时间】:2019-03-29 18:24:54
【问题描述】:

在下面的代码sn-p中,

void foo() {
  std::this_thread::native_handle().... //error here
}

int main() {
  std::thread t1(foo);

  t1.join();
  return 0;
}

如何从函数foo 中的std::this_thread 中获取native_handle

【问题讨论】:

    标签: c++ c++11 stdthread


    【解决方案1】:

    线程无法自主访问自己的std::thread。这是故意的,因为std::thread 是只能移动的类型。

    我相信您要求的是std::thread::idnative_handle() 成员,这是一个有趣的建议。据我所知,目前是不可能的。它会像这样使用:

    void foo()
    {
        auto native_me = std::this_thread::get_id().native_handle();
        // ...
    }
    

    它不能保证工作,甚至存在。不过我想大多数 POSIX 平台都可以支持它。

    尝试更改 C++ 标准的一种方法是提交问题。 Here 是有关如何执行此操作的说明。

    【讨论】:

    • 你认为这样的东西值得作为 C++14 的提案提交吗?
    • @NicholasPezolano:目前没有。但是,我可能会被一个激励性的用例和一个演示它的实现所说服。 IE。我想我知道成本/风险。但我不认为我知道它的好处。如果收益为零,那么无论成本多低,收益/成本比都很差。所以你需要证明一个很大的好处。
    • 我认为 OP 不一定想要std::thread::id::native_handle。我认为有趣的一点是:std::this_thread 的界面不应该模仿std::thread 的界面吗?当然,除了那些与线程生命周期管理相关的成员,正如您正确指出的那样,这并没有太大意义。这并没有留下太多,但native_handle 让我觉得明显缺席。
    • @NicholasPezolano:可能,不要卖空自己。我的观点是,向委员会推销某些东西有助于他们了解为什么需要某些东西。当你只是说:我们为什么不这样做时,它几乎没有多大帮助。我个人从未制作过跨平台线程分析器/调试器。所以我不知道这将如何大大简化事情。但我发现自己希望我知道。一篇由你自己撰写的更详细地解释事情的论文可能会激励委员会。或者它可能不会。未来很难预测。
    • 为什么不用std::this_thread::native_handle(),就像get_id() 一样?这可以被视为“完成”——这两件事在所有线程系统中都可用,两件事在逻辑上都是一样的。如果this_thread::native_handle() 有问题,std::thread::native_handle() 也可以这样说。您需要激励用例吗?考虑调试。 Gdb 不会向您显示 ID 由this_thread::get_id() 返回的线程列表。
    【解决方案2】:

    C++11 没有提供获取当前线程 native_handle 的机制。您必须使用特定于平台的调用,即 Windows 上的 GetCurrentThread():

    void foo()
    {
        auto native_me = ::GetCurrentThread();
    }
    

    【讨论】:

    • 不能为我自己的帖子投票,但是当我再次遇到这个问题并遇到这个答案时,我大声笑了起来!
    【解决方案3】:

    正如霍华德所指出的,ISO C++ 中尚不支持此功能。

    但是thread::id 有一个重载的operator<<打印 自身到ostream

    #include <iostream>
    #include <thread>
    
    int main()
    {
        std::cout << "Current thread ID: " << std::this_thread::get_id() << std::endl;
    }
    

    在不知道实际值的语义(高度依赖于平台)的情况下,打印它或将其用作映射中的键是您应该做的最多的事情。

    【讨论】:

      【解决方案4】:

      目前(C++17)你不能从std::this_thread得到native_handle

      最可能的接口可能是std::this_thread::native_handle()。但不是std::this_thread::get_id().native_handle();@Howard

      由于 Win/Linux/MacOS 以不同方式实现 threadthread::id:(以下是非正式伪代码)

      • 在 Linux 上,native_handle 存储在线程中。_M_id(id 类型)._M_thread。
      • 在 Windows 上,native_handle 存储在线程中。_Thr(类型为 _Thrd_t,不是类型 id)。_Hnd。
      • 在 MacOS 上,native_handle 存储在 thread.__t_。

      您只能在 Linux 源代码中看到 native_hanlde 对象在 thread::id 结构中实现。因此,在 Win/MacOS 上,您无法从 id 对象中获取 native_handle

      最后,如果您的代码仅在 Linux 中运行,则有一个从 this_thread 获取 native_handle 的肮脏技巧,我绝不会推荐:

      auto thread_id = std::this_thread::get_id();
      auto native_handle = *reinterpret_cast<std::thread::native_handle_type*>(&thread_id);
      

      【讨论】:

        【解决方案5】:

        事实上,有一种有趣的方法可以规避问题并通过 std::thread 访问它,这在某些情况下可能有效。 原始示例发布在此blog 上。我重写了它。 您可以将下面的代码保存到 test.cpp 并编译并运行它 :

        // g++ ./test.cpp  -lpthread && ./a.out
        // 
        #include <thread>
        #include <vector>
        #include <iostream>
        #include <mutex>
        #include <sched.h>
        #include <pthread.h>
        int main(int argc, const char** argv) {
          constexpr unsigned num_threads = 4;
          // A mutex ensures orderly access to std::cout from multiple threads.
          std::mutex iomutex;
          std::vector<std::thread> threads(num_threads);
          for (unsigned i = 0; i < num_threads; ++i) {
            threads[i] = std::thread([&iomutex, i,&threads] {
              // Create a cpu_set_t object representing a set of CPUs. Clear it and mark
              // only CPU i as set.
              cpu_set_t cpuset;
              CPU_ZERO(&cpuset);
              CPU_SET(i, &cpuset);
              int rc = pthread_setaffinity_np(threads[i].native_handle(),
                                              sizeof(cpu_set_t), &cpuset);
              if (rc != 0) {
                std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n";
              }
              std::this_thread::sleep_for(std::chrono::milliseconds(20));
              while (1) {
                {
                  // Use a lexical scope and lock_guard to safely lock the mutex only
                  // for the duration of std::cout usage.
                  std::lock_guard<std::mutex> iolock(iomutex);
                  std::cout << "Thread #" << i << ": on CPU " << sched_getcpu() << "\n";
                }
        
                // Simulate important work done by the tread by sleeping for a bit...
                std::this_thread::sleep_for(std::chrono::milliseconds(900));
              }
            });
        
        
          }
        
          for (auto& t : threads) {
            t.join();
          }
          return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 2012-02-26
          • 1970-01-01
          • 2016-12-20
          • 1970-01-01
          • 2015-08-22
          • 2010-11-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多