4

Linux is a new platform to me. I've coded on Windows in c++ for a number of years and have become comfortable with multithreading on that platform.

Along comes C++11 at a time when I need to learn c++ on the linux platform.

Linux appears to use pthreads for the most part - okay there's also boost::threads and QT have their own threads too. But with C++11 comes std::thread, a whole new (cross platform and C++ standard) way to do threads.

So I guess I'll have to learn pthreads and std::threads. Ultimately, std::thread seems more important, but there's a lot of legacy code out there, so I'll have to know both.

For thread synchronization on windows, I would use WaitForMultipleObjects to wait for a number of tasks to complete before continuing with further work.

Does a similar synchronization mechanism exist for pthreads? std::threads?

I've had a look at pthread_join, and it seems to have the facility to only wait on one thread at a time. Am I missing another pthread call maybe?

  • AFAIK, the `std::thread` interface is based on pthreads, to some extent. – R. Martinho Fernandes May 30 '12 at 14:27
  • 1
    It seems more closely based on boost::threads: http://www.boost.org/doc/libs/1_49_0/doc/html/thread.html –  May 30 '12 at 14:30
  • 1
    I'm sure it comes down to pthreads under the hood. – MK. May 30 '12 at 14:36
  • Well, as long as you just wait for a bunch of threads, wouldn't a loop of joins suffice as a replacement for `WaitForMultipleObjects`? – Christian Rau May 30 '12 at 14:37
  • 1
    em, No. WaitForMultipleObjects is much more powerful than that. http://blog.fpmurphy.com/2009/04/porting-waitforsingleobject-to-gnulinux.html WaitForSingleObject and its cousins can wait for a signal from any or all of the following “objects”: change notification, console input, event, job, memory resource notification, mutex, process, semaphore, thread and waitable timer and in limited circumstances on files and file I/O. No published standardized API in the GNU/Linux or Unix world comes close to handling this range of objects in a single API. –  May 30 '12 at 14:41
  • @freefallr yes, and boost::threads was based on just::thread, which, AFAIK was based on pthreads, but with C++ idioms :) – R. Martinho Fernandes May 30 '12 at 14:41
  • 1
    @freefallr I know, that's why I wrote *"as long as you just wait for a bunch of threads"* (and why I didn't make it an answer). For locking a bunch of mutexes (or other lockables), you also have `std::lock` (and yes, I know `WaitForMultipleObjects` can do even more, pay attention to the premise). – Christian Rau May 30 '12 at 14:45

5 Answers5

8

std::thread is boost::thread accepted into C++11 with some extras. My understanding is that if boost::thread gets replaced in code with std::thread it should still compile and work.

boost::thread is based on pthreads design, providing thin C++ wrappers over thread, mutex and condition variables. Thread cancellation though was left outside the scope of C++11, since there was no agreement how it should work in C++.

So, by learning pthreads you also learn std::thread concepts. std::thread adds mostly syntax sugar and convenience functions on top of pthreads C API.

With regards to WaitForMultipleObjects(), neither pthreads nor std::thread provide anything similar to its bWaitAll=FALSE mode, however, it's routinely simulated using pipes and select() on UNIX, or more modern eventfd() and epoll() on Linux. bWaitAll=TRUE mode can be simulated by waiting on all tasks in turn, since it doesn't proceed until all objects are ready anyway.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • And they (C++ threads and pthreads) won't in turn deviate that much from what you (OP) are acquainted with from Win32, as, well, a thread is a thread is a thread, locks a mutex, locks a mutex, locks a mutex. Though you may miss Win32's general events, but can finally embrace condition variables. – Christian Rau May 30 '12 at 14:41
  • win32 thread API was different and, for example, didn't provide condition variables natively when I last programmed it (it was implemented in `boost::thread` using semaphores). – Maxim Egorushkin May 30 '12 at 14:44
  • Nice answer, but I dont see how it answers the OP question about: ` WaitForMultipleObjects to wait for a number of tasks to complete before continuing with further work. Does a similar synchronization mechanism exist for pthreads? std::threads?` – Brady May 30 '12 at 14:55
  • Added a note regarding `WaitForMultipleObjects` now. – Maxim Egorushkin May 30 '12 at 15:03
1

No, neither pthreads nor C++11 has direct equivalent of WaitForMultipleObjects (i.e. wait for any waitable "handle" type.) pthread_join can only be used to join threads, and only a single, specific thread.

The closest equivalent on posix platforms is to wait for multiple file descriptors using system calls such as select(), poll() or the linux-specific epoll(), but they require you to have a file descriptor to wait on, which is fine for I/O events but requires extra work from you to use them wait for mutexes, condition variables or other synchronisation objects. There are more general event libraries built on top of those system calls, e.g. libevent and libev and Boost ASIO, which support waiting for timers as well as I/O, but still not thread completion, mutex locks etc. with a single function like WaitForMultipleObjects

The alternatives you do have for pthreads and C++11 threads are to wait on different synchronisation types separately. You can wait for timers, wait for threads to complete, wait for mutexes, wait on condition variables, wait for asynchronous results to be ready (std::async in C++11, no direct equivalent in pthreads) ... but there's no call that will allow you to wait a heterogeneous set of those types all at once.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Actually, posix has the Conditional Variable `pthread_cond_t`, which can be used to make a barrier sync. – Brady May 30 '12 at 14:59
  • Yes, but you have to do a lot of work to use it for synchronising on multiple objects, it's not even close to `WaitForMultipleObjects`. A condition variable only lets you wait for a signal on that condition variable, how do you set up a signal on the condvar when any one of a set of multiple events happens? e.g. I have four threads and two sockets, how do I use a condition variable to wait until any thread completes or there is data to be read on a socket? It requires considerable extra work. – Jonathan Wakely May 30 '12 at 15:15
0

I could give you a really fancy answer but alas, this is where I learned them and it is a good introduction:

http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

You use pthread_mutex_t for syncronization and pthread_join probably handles the wait for multiple tasks problem. It works exactly as you would expect.

Jonathan Henson
  • 8,076
  • 3
  • 28
  • 52
0

Regarding WaitForMultipleObjects, this is generally called a Barrier Sync. Boost has an implementation called barrier. It uses conditional variables to implement it, in posix its a pthread_cond_t

Here is an answer I left recently explaining barrier sync.

Community
  • 1
  • 1
Brady
  • 10,207
  • 2
  • 20
  • 59
  • 1
    That's not even close to WaitForMultipleObjects. And `pthread_barrier_wait` would have been simpler for your example. – Jonathan Wakely May 30 '12 at 15:25
  • 1
    @JonathanWakely, I stand corrected, I didnt know that pthread_barrier_wait existed, I know about the boost impl and just "copied" what I needed. I wonder why boost "re-implements" it... Maybe to make it portable?? Thanks for the info. – Brady May 30 '12 at 16:24
  • 1
    Probably for portability, `pthread_barrier_wait` was optional in POSIX 2001, but is now part of the base spec in POSIX 2008. – Jonathan Wakely May 30 '12 at 16:31
0

Based on this, you must call pthread_join for each single thread you have created. Or to use mutexes, if there is a need to synchronize your threads.

besworland
  • 747
  • 2
  • 7
  • 17