Reputation: 5675
I have access to a std::thread::id
in my code, and need to use some native functions that receive as argument ThreadId as DWORD
( same as returned by GetCurrentThreadId()
).
I cannot find any way to convert from std::thread::id
to a Win32 DWORD
ThreadId. The closest thing I can find is std::thread
has that has a native_handle. But I still have no way to create the std::thread
to get the native_handle from a std::thread::id
, so I am still too far from what I need.
Is there something that I am missing? Or is the gap between standard portable thread functions and native functions so big that the standard api is unusable for my purposes?
Upvotes: 5
Views: 2987
Reputation: 463
here's rtl implementation specific approach to get internal thread id representation from std::thread::id, see here
//
#include <iostream>
#include <thread>
#ifdef _WIN32
#include <Windows.h>
#endif
namespace ns
{
struct dummy{};
using thread_id_access=std::basic_ostream<dummy>;
}
namespace std
{
template <>
class basic_ostream<ns::dummy>
{
public:
#if defined(_WIN32)
using id_type=unsigned int;
#elif defined(_GLIBCXX_RELEASE)
using id_type=std::thread::native_handle_type;
#else
#error Consult your rtl implementation
#endif
id_type id=0;
};
template<>
ns::thread_id_access & operator <<(ns::thread_id_access & os, std::thread::id id)
{
#if defined(_GLIBCXX_RELEASE)
os.id=id._M_thread;
#elif defined(_MSC_VER)
os.id=id._Id;
#else
#error Consult your rtl implementation
#endif
return os;
}
}
namespace ns
{
inline auto GetThreadId(std::thread::id id)
{
thread_id_access t;
t<<id;
return t.id;
}
}
int main()
{
auto const id=std::this_thread::get_id();
std::cout<<std::hex<<id<<"\n";
std::cout<<std::hex<<ns::GetThreadId(id)<<"\n";
#ifdef _WIN32
std::cout<<GetCurrentThreadId()<<"\n";
#endif
return 0;
}
Upvotes: 1
Reputation: 1047
You can easily get the Windows thread identifier, at least in Visual C++. std::thread::native_handle()
returns a Win32 thread handle, and the Win32 API function GetThreadId()
returns a thread identifier:
#include <thread>
void stopGUIThread(std::thread& guiThread)
{
if (guiThread.joinable())
{
auto threadId = ::GetThreadId(guiThread.native_handle());
assert(threadId != 0);
// PostThreadMessage() will return 0 if the thread has
// already finished its execution.
::PostThreadMessage(threadId, WM_QUIT, 0, 0);
guiThread.join();
}
}
Upvotes: 1
Reputation: 275385
This answer will presume you are using microsofts std::thread
example from MSVC2015, and that documented facts about it will not change in the future.
There is no way to go from std::thread::id
to native_handle
under the docs.
You could attempt to maintain a table from std::thread::id
to std::thread
or native_handle
s, but that in practice requires a bottleneck where you can control all std::thread
creation. Which seems a bit much.
If you test the value of the std::thread::id
integer, you'll find it is the same as the native handle in bits at the current time. So you can engage in rather horrible undefined behavior and extract the bits and convert to an integer. Doing so is not advised, as you are relying that microsoft never changes its non-documented details of its implementation; it is a bug and maintenance nightmare waiting to happen.
So seek to solve your problem a different way. Request native_handle
s directly, or solve your problem without the native APIs. In many cases use of native APIs is a bad sign; half of such use involves attempting to suspend or terminate a thread from outside the thread, which is a really really bad idea in C++ (and in general, really).
Upvotes: 2