Coder777
Coder777

Reputation: 1035

is it safe to cast uintptr_t returned by _beginthread to HANDLE?

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

Answers (2)

IInspectable
IInspectable

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

Jonathan Potter
Jonathan Potter

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

Related Questions