Reputation: 1035
1)The answer from this post WaitForSingleObject : how to get handle from _beginthreadex say that it is only legal to cast uintptr_t returned _beginthreadex to type HANDLE, then is it not safe to convert uintptr_t returned _beginthread to type HANDLE?
2)We have cast like below in a 32-bit application and it seems to be working well, will I run into any issues when I convert this app to 64-bit? HANDLE thread = (HANDLE)_beginthread(checkThread, 0, &thrVal);
3) Is it worth to convert all the _beginthread calls to _beginthreadex?
Upvotes: 2
Views: 1364
Reputation: 51489
If you want to use the Windows synchronization APIs you need a HANDLE
you control. Using the uintptr_t
returned from _beginthread
cannot safely be cast to a HANDLE
value for use with the synchronization APIs. The documentation for _beginthread, _beginthradex is pretty clear here (emphasis mine):
You can also use the thread handle that's returned by _beginthreadex with the synchronization APIs, which you cannot do with _beginthread.
If you don't want to rely on undocumented behavior you must use _beginthreadex
if you need a HANDLE
value for use with the synchronization APIs.
Upvotes: 2
Reputation: 37192
I think the answer to the question you linked is misleading, or at least incomplete. According to the docs for beginthread()
and beginthreadex()
:
If successful, each of these functions returns a handle to the newly created thread
The difference between the two is that threads started by beginthread()
close their own handles when they exit. So it's not safe to wait on a handle returned by beginthread()
because it may have been closed or recycled by the time you wait on it. However if you have control over the thread you launched (by using some other form of synchronisation) you could call DuplicateHandle()
to get a handle that is safe to wait on.
In an x64 build, uintptr_t
is defined as a 64 bit value:
typedef unsigned __int64 uintptr_t;
So casting this to a HANDLE
in this case is safe and is indeed what you're meant to do.
_beginthreadex()
gives you more control over the new thread, including the ability to start it in a suspended state, and retrieve the thread ID. It also returns a HANDLE
that you are responsible for closing, which means it's safe to wait on it. It's a more useful, versatile function, but if you don't have a need for those additional features there's no reason to switch just for the sake of it.
Upvotes: 0