C11 Threads in Visual Studio 2022 version 17.8 Preview 2
C11 Threads in Visual Studio 2022 version 17.8 Preview 2 Charlie Barto September 26th, 20232 3 Back in Visual Studio 2022 version 17.5 Microsoft Visual C gained preliminary support for C11 atomics. We are happy to announce that support for the other major concurrency feature of C11, threads, is available in Visual Studio version 17.8 Preview 2. This should make it easier to port cross-platform C applications to Windows, without having to drag along a threading compatibility layer. Unlike C11 atomics, C11 threads do not share an ABI with C++’s facilities, but C++ programs can include the C11 threads header and call the functions just like any C program. Both are implemented in terms of the primitives provided by Windows, so their usage can be mixed in the same program and on the same thread. The implementations are distinct, however, for example you can’t use the C11 mutexes with C++ condition variables. C11 contains support for threads and a variety of related concurrency primitives including mutexes, condition variables, and thread specific storage. All of these are implemented in Visual Studio version 17.8 Preview 2. Threads Threads are created with thrd_create, to which you pass a pointer to the desired entry point and a user data pointer (which may be null), along with a pointer to a thrd_t structure to fill in. Once you have a thrd_t created with thrd_create you can call functions to compare it to another thrd_t, join it, or detach it. Functions are also provided to sleep or yield the current thread. int thread_entry(void* data) { return 0; } int main(void) { thrd_t thread; int result = thrd_create(&thread, thread_entry, NULL); if(result != thrd_success) { // handle error } result = thrd_join(thread, NULL); if(result != thrd_success) { // handle error } return 0; } A key difference between our implementation and C11 threads implementations based on pthreads is that threads can not detach themselves using thrd_current() and thrd_detach(). This is because of a fundamental difference in how threads work on Windows vs Unix descendants and we would require a shared datastructure that tracks thread handles to implement the typical behavior. On Unix derivatives the integer thread ID is the handle to the thread and detaching just sets a flag causing the thread to be cleaned up immediately when it finishes. This makes detached threads somewhat dangerous to use on Unix derivatives, since after a detached thread exits any other references to that thread ID will be dangling and could later refer to a different thread altogether. On Windows the handle to a thread is a win32 HANDLE and is reference counted. The thread is cleaned up when the last handle is closed. There is no way to close all handles to a thread except by keeping track of them and closing each one. We could implement the Unix/pthreads behavior by keeping a shared mapping of thread-id to handle, populated by thrd_create. If you need this functionality then you can implement something like this yourself, but we don’t provide it by default because it would incur a cost even if it’s not used. Better workarounds may also be available, such as passing a pointer to the thrd_t populated by thrd_create via the user data pointer to the created thread. Mutexes Mutexes are provided through the mtx_t structure and […]
