【发布时间】: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?
【问题讨论】:
在下面的代码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?
【问题讨论】:
线程无法自主访问自己的std::thread。这是故意的,因为std::thread 是只能移动的类型。
我相信您要求的是std::thread::id 的native_handle() 成员,这是一个有趣的建议。据我所知,目前是不可能的。它会像这样使用:
void foo()
{
auto native_me = std::this_thread::get_id().native_handle();
// ...
}
它不能保证工作,甚至存在。不过我想大多数 POSIX 平台都可以支持它。
尝试更改 C++ 标准的一种方法是提交问题。 Here 是有关如何执行此操作的说明。
【讨论】:
std::thread::id::native_handle。我认为有趣的一点是:std::this_thread 的界面不应该模仿std::thread 的界面吗?当然,除了那些与线程生命周期管理相关的成员,正如您正确指出的那样,这并没有太大意义。这并没有留下太多,但native_handle 让我觉得明显缺席。
std::this_thread::native_handle(),就像get_id() 一样?这可以被视为“完成”——这两件事在所有线程系统中都可用,两件事在逻辑上都是一样的。如果this_thread::native_handle() 有问题,std::thread::native_handle() 也可以这样说。您需要激励用例吗?考虑调试。 Gdb 不会向您显示 ID 由this_thread::get_id() 返回的线程列表。
C++11 没有提供获取当前线程 native_handle 的机制。您必须使用特定于平台的调用,即 Windows 上的 GetCurrentThread():
void foo()
{
auto native_me = ::GetCurrentThread();
}
【讨论】:
正如霍华德所指出的,ISO C++ 中尚不支持此功能。
但是thread::id 有一个重载的operator<< 以打印 自身到ostream。
#include <iostream>
#include <thread>
int main()
{
std::cout << "Current thread ID: " << std::this_thread::get_id() << std::endl;
}
在不知道实际值的语义(高度依赖于平台)的情况下,打印它或将其用作映射中的键是您应该做的最多的事情。
【讨论】:
目前(C++17)你不能从std::this_thread得到native_handle
最可能的接口可能是std::this_thread::native_handle()。但不是std::this_thread::get_id().native_handle();@Howard
由于 Win/Linux/MacOS 以不同方式实现 thread 和 thread::id:(以下是非正式伪代码)
native_handle 存储在线程中。_M_id(id 类型)._M_thread。native_handle 存储在线程中。_Thr(类型为 _Thrd_t,不是类型 id)。_Hnd。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);
【讨论】:
事实上,有一种有趣的方法可以规避问题并通过 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;
}
【讨论】: