Should I use condition variables from the C++ standard or from the Windows API?
Asked Answered
E

2

6

When implementing condition variables into a Win32 C++ program, would it be better to use Win32 functions, classes, and data types (e.g. CreateThread, SleepConditionVariableCS, WaitForSingleObjectEx, ReleaseMutex, CONDITION_VARIABLE) or those from the C++11 standard libraries (e.g. thread, wait, join, unlock, condition_variable)?

Since the answer to this question is probably not binary, what considerations should one take into account when making such a decision?

Eba answered 27/1, 2014 at 16:8 Comment(7)
Given that visual studio isn't done implementing the standard, if portability isn't an issue, I'd use the windows calls for now.Seldun
Functions have preconditions and postconditions. When you write software, you have "purposes". Functions may satisfy your purposes or not, but they are not "better" or "worse". They are just functions.Figurine
@Seldun I'm actually using Code::Blocks and the latest version of MinGW, but that's a good consideration.Eba
Do you ever plan to be cross-platform?Swetlana
@Swetlana Of course you're right, a desire for (even potential) cross-platform functionality would make the decision clear; I'm wondering what else should be considered (assuming portability is irrelevant).Eba
@DanielDaranas Correct. That's a point I already addressed in the final sentence of my question. I don't know what potential benefits either set of functions may have.Eba
In some cases there isn't a like-for-like comparison. CreateEvent() for instance, can be replicated with a std::condition_varaible, but the underlying implementation is different enough that there can be performance differences when trying to use the constructs.Swetlana
T
6

The C++ synchronization mechanisms are designed to C++ principles. They free their resources in the destructor, and they also use RAII to ensure safe locking. They use exceptions to signal errors.

Essentially, they are much harder to use incorrectly than the function-based native Windows API. This means that if you can use them (your implementation supports them), you always should use them.

Oh, and they are cross-platform.

Twocycle answered 27/1, 2014 at 16:21 Comment(5)
I completely agree. If you ever need the native handles of those objects, use the native_handle() method, with the understanding that the native handle may not be always available, or it may not be what you think it is. For example, a mutex in the C++11 library implementation may use an atomic variable for the uncontested case, so there won't be a native handle available for anything unless the mutex is contested.Whitethorn
A small note on the side: VC2012's implementation of the thread library has quite a few bugs left which can leave you with ugly race conditions. So unless you are already working with VC2013, consider using Boost's implementation of the thread library instead, which is much more mature. You shouldn't notice any difference in performance between the two, as they are both rather thin wrappers around the native Win32 functions.Darelldarelle
Whether they're cross-platform or not is irrelevant if the program already contains other Win32 code though, right? Unless portions of the code might possibly be re-purposed into portable code. Of course, the advantage of me learning one or the other is that the resulting knowledge could be cross-platform.Eba
Yeah. You learn the cross-platform code, you can reuse the parts that are cross-platform, and you have less work if you ever want to port.Twocycle
Indeed, after further research and implementing my own condition variable, I now understand that the use of RAII and exceptions in C++ Standard Library classes such as thread, mutex, and condition_variable is quite well done and makes handling errors simpler than handling errors in Win32 functions. Also, once you understand these classes, they're surprisingly easy to use.Eba
E
1

One consideration should be what your compiler can handle. For example, when you install MinGW on Windows, you can choose whether to install the API for POSIX threads or Win32 threads. On the other hand, if you use TDM-GCC, you should be aware that versions 4.7.1 and lower use Win32 threads, while versions 4.8.1 and higher use POSIX threads. And as woolstar mentioned above, if you're using Microsoft's compiler, you should check to see whether the bugs in its support for these classes have been worked out.

If your compiler supports POSIX threads, you can use the C++ thread classes of the Standard Library (e.g. thread, mutex, condition_variable). If your compiler supports Win32 threads, you can use the Win32 thread functions.

In my case, I originally had TDM-GCC 4.7.1 and tried to use the C++ Standard Library classes, but that didn't work (for reasons explained above). So I installed MinGW by itself and chose "posix" in the "threads" option of the installer. Then I was able to use those classes.

Eba answered 4/2, 2014 at 10:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.