C++11 'native_handle' is not a member of 'std::this_thread'
Asked Answered
F

5

19

In the following code snippet,

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

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

  t1.join();
  return 0;
}

How do you get the native_handle from std::this_thread from within the function foo?

Fairish answered 28/4, 2013 at 3:22 Comment(1)
please also see my other answer to somewhat related question hereKalisz
E
15

There is no way for a thread to autonomously gain access to its own std::thread. This is on purpose since std::thread is a move-only type.

I believe what you're requesting is a native_handle() member of std::thread::id, and that is an interesting suggestion. As far as I know it is not currently possible. It would be used like:

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

It wouldn't be guaranteed to work, or even exist. However I imagine most POSIX platforms could support it.

One way to try to change the C++ standard is to submit issues. Here are directions on how to do so.

Estus answered 28/4, 2013 at 3:33 Comment(7)
do you think something like this is worth submitting as a proposal for C++14?Fairish
@NicholasPezolano: At this time no. However I could be persuaded by a motivating use case and an implementation demonstrating it. I.e. I think I know the cost/risk. But I don't think I know the benefit. If the benefit is zero, then no matter how low the cost, the benefit/cost ratio is poor. So you would need to demonstrate a large benefit.Estus
I don't think the OP necessarily wants std::thread::id::native_handle. I think the interesting point is: shouldn't the interface of std::this_thread mimic that of std::thread? Except of course for those members that relate to thread lifetime management, which as you rightfully point out doesn't make too much sense. That doesn't leave much, but native_handle strikes me as conspicuously absent.Aeronaut
@HowardHinnant I wanted to make a cross platform thread profiler/debugger,this would simplify things greatly, i'm sure that does not qualify as a large benefit however.Fairish
@NicholasPezolano: It might, don't sell yourself short. My point is that to sell something to the committee, it helps for them to see why something is needed. It doesn't help nearly as much when you just say: why don't we do this. I've personally never made a cross platform thread profiler/debugger. So I'm clueless how this would simplify things greatly. But I find myself wishing I knew. A paper authored by yourself explaining things in more detail might motivate the committee. Or it might not. It is hard to predict the future.Estus
Why not std::this_thread::native_handle(), just like it's with get_id()? This can be treated as "completion" - both things are available in all thread systems, both things do the same logically. If there's something wrong with this_thread::native_handle(), the same can be said about std::thread::native_handle(). You need motivating use case? Think about debugging. Gdb won't show you a list of thread with ID's returned by this_thread::get_id().Tenedos
see also https://mcmap.net/q/189225/-retrieve-the-windows-thread-identifier-from-the-std-thread-id-structureKalisz
C
11

C++11 does not provide a mechanism for getting the current threads native_handle. You must use platform specific calls, i.e. GetCurrentThread() on Windows:

void foo()
{
    auto native_me = ::GetCurrentThread();
}
Copyright answered 7/10, 2014 at 13:33 Comment(1)
Can't vote for my own post, but laughed out loud when I hit this problem again and came across this answer!Copyright
B
2

As Howard pointed, there is no support for this in ISO C++ yet.

But thread::id has an overloaded operator<< to print itself to an ostream.

#include <iostream>
#include <thread>

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

Without knowing the semantics of the actual value (which is highly platform-dependent), printing it or using it as a key in a map is the most you should be doing anyway.

Baresark answered 3/10, 2017 at 14:56 Comment(0)
S
1

Currently(C++17) you can't get native_handle from std::this_thread

The most possible interface might be std::this_thread::native_handle(). But not std::this_thread::get_id().native_handle(); by @Howard

Since Win/Linux/MacOS implement thread and thread::id differently: (below is informal pseudo code)

  • On Linux native_handle is stored at thread._M_id(of type id)._M_thread.
  • On Windows native_handle is stored at thread._Thr(of type _Thrd_t, not of type id)._Hnd.
  • On MacOS native_handle is stored at thread.__t_.

As you can see only in Linux source there is native_hanlde object implemented in thread::id structure. Thus on Win/MacOS you can't get the native_handle from an id object.

Finally, if your code runs only in Linux, there is a dirty trick to get native_handle from this_thread which I will never recommend:

auto thread_id = std::this_thread::get_id();
auto native_handle = *reinterpret_cast<std::thread::native_handle_type*>(&thread_id);
Spanking answered 17/6, 2020 at 8:26 Comment(1)
T
0

In fact, there is one funny way to circumvent the problem and access it via std::thread , which may work in some cases. The original example was posted on this blog. I rewritten it. You can save the code below to test.cpp and compile & run it :

// 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;
}
Tertias answered 1/6, 2021 at 8:30 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.