17

What are the pros, cons and consequences of using C++11 std::thread vs WinAPI functions (such as CreateThread, _beginthreadex, etc.) ?

Agnel Kurian
  • 57,975
  • 43
  • 146
  • 217
KaMyLuS
  • 219
  • 1
  • 2
  • 4
  • 5
    `std::thread` is better because it's standard and portable – Charles Salvia Aug 09 '14 at 17:36
  • 2
    `std::thread` enables you to write cross-platform applications. And, if you still need to do something platform-specific with a thread created via this API, you can obtain the implementation handle via `native_handle`, and pass it to platform-specific functions. – Daniel Kamil Kozar Aug 09 '14 at 17:41
  • 2
    Note that on Windows, you shouldn't use ``CreateThread``, you should use ``_beginthreadex`` so that the CRT's thread-local-storage is properly initialized. ``std::thread`` is the C++11 way to do it, and on Microsoft platforms it makes use of ConCRT/ppl. ``std::thread`` has the advantage of working for Windows Store apps, where the other thread APIs are not available there. – Chuck Walbourn Aug 09 '14 at 18:08
  • @ChuckWalbourn: CreateThread really isn't a problem any more, except in a few rare edge cases (most notably if the app is has to cope when critically short of memory or address space). Under normal circumstances, the CRT will initialize its storage on the fly as necessary. – Harry Johnston Aug 09 '14 at 23:40
  • FWIW, `std::unique_ptr` makes RAII with `CreateThread` possible -- use `CloseHandle` as the deleter function. – Ben Voigt Aug 28 '14 at 14:33
  • Define "better" (or alternatively, the standpoints you're interested in judging this from) or this is "opinion-based". – ivan_pozdeev Jan 15 '16 at 23:03

3 Answers3

39

Portability

std::thread is new to C++11 standard - with it, you can write portable code in C++ across compilers supporting C++11. You can feel the future in it.

It is based on boost::thread, which supports older compilers not supporting C++11 - which makes porting to other platforms even easier.

If you need to use platform specific tricks, std::thread::native_handle is the way to go.

CreateThread is specific to WinAPI, this implies writing non-portable code. Also, this API is quite old and more inconvenient to use.

RAII

WinAPI is a C API which does not encourage modern C++ good practices. Every threading primitive you create, you must later destroy manually.

This is not the case for thread library in C++11, and this makes higher-level abstractions easier to write. While std::thread is still fairly low-level (either you .join() or .detach() your thread, or the thread destructor will terminate your program), C++11 threading library has std::lock_guard and other lock classes for supporting RAII for mutexes.

While C++11 has some higher-level abstractions, like std::async for launching functions asynchronously, it does not provide other abstractions like threadpools, so you may want to use other libraries.

Type safety

WinAPI can only call function pointers with specific signature - which is prone to bugs related to type safety, lifetime of objects and mismanaging memory.

std::thread can call any callable object:

// call free-standing function in a separate thread
std::thread first(func);

// call free-standing function with arguments (1, 2), in a separate thread
std::thread second(func, 1, 2); 

// call static member function in a separate thread
std::thread third(&A::static_memfun); 

// call non-static member of a temporary in a separate thread
std::thread fourth(&A::memfun, A());

//call std::function in a separate thread
std::function<void(int)> callback = std::bind(func, 1, _1);
std::thread fifth(callback, 2);

// call a function object
Functor f;
std::thread sixth(f);

TL;DR: There is no reason to use WinAPI threads as the main threading mechanism in new C++ code.

Community
  • 1
  • 1
milleniumbug
  • 15,379
  • 3
  • 47
  • 71
  • 15
    Feel the `future`, haha. – Quentin Aug 09 '14 at 17:51
  • @Quentin and experience `broken_promise`s – Swift - Friday Pie Dec 29 '16 at 05:53
  • 1
    Also keep in mind that using `std::thread` instead of `CreateThread` will significantly increase the memory usage and executable size of your program, depending on several factors like amount of threads created, static vs dynamic linking and compile optimizations. – GetFree Aug 12 '17 at 00:11
  • 2
    @GetFree [citation needed] – milleniumbug Aug 12 '17 at 00:27
  • @milleniumbug, I've seen it myself on my projects when I decided to try the new C++ threads. All you need to do is replace your `CreateThread` calls with `std::thread var(...)` and it will work right away. Then just compare the result with you old executable. – GetFree Aug 12 '17 at 02:36
10

Cross-platformity is a small benefit. The real benefit is in the interface. std::thread offers RAII-guarantees as to the cleanup of the thread, and supports arbitrary function object arguments instead of just function pointers. std::thread is the C++11 wrapper on CreateThreadEX and it is that way for a reason.

Just as a side note, std::thread is a terrible, terrible API. If you're creating threads yourself, you're probably doing it wrong. Use a real threading API like Intel's TBB or Microsoft's PPL, which are vastly superior to the terrible std::thread and somehow even worse CreateThreadEx. std::thread is like, "I offered you cross-platform mmap, so you could write your own malloc on top, enjoy!".

peterh
  • 11,875
  • 18
  • 85
  • 108
Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 2
    Well, I'd rather make my own `malloc` on top of `mmap` than only having `malloc` and trying to hack a `mmap` on top of it. Being low level isn't terrible. Without the low level stuff, we would never have the nice high level features – youdontneedtothankme Aug 09 '14 at 21:59
  • @youdontneedtothankme: You're right. Except that virtually nobody can actually implement thread abstractions properly on top of `std::thread`, and only the implementer needs `std::thread`, not the user. – Puppy Aug 10 '14 at 06:58
  • 2
    `std::thread` isn't even a RAII class (at least not in the classic sense): It's destructor doesn't clean up the thread - it terminates the program. – MikeMB Dec 15 '16 at 22:08
3

You should probably use std::thread.

std::thread is part of the (new) standard, and is portable.

Unless you're only targeting Windows AND you need to interact with your threads using the WinAPI, std::thread is the way to go.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93