Can C++11's Mutexes be used for Inter-Process Communication? In other words, can it be used for shared memory and signalling an event?

Currently, I'm using CreateEvent and SetEvent from WINAPI and I wanted a cross-platform way of doing so without doing #ifdef windows and ifdef linux, etc..

I use CreateEvent and have one process wait until the event signals. The other then signals when it's done reading and it repeats and so on..

Recommended Answers

All 3 Replies

Can C++11's Mutexes be used for Inter-Process Communication? In other words, can it be used for shared memory and signalling an event?

Yes. But the more important question is: Should mutexes be used for that? No. To use a mutex (or pair of mutexes) for this purpose, one could come up with a number of schemes. In any case, the scheme will be based on having one thread locking the mutex while the other waits to get a lock on it, and the unlock-lock transition would be the "signal" event. There are a number of problems with that. First, the way that a thread waits to get a lock on a mutex is generally implemented (this is OS dependent) in a loop like this:

while( check_if_mutex_is_available() )
  yield_thread_scheduled_time();

which is generally performed at the kernel level. This is rather inefficient, mostly because a mutex is not meant to be used that way. A mutex is meant to prevent two mutually exclusive codes from being executed at the same time, not as an event-based synchronization device.

The second problem are all the edge cases when the threads are running fast and are racing each other. You can have misses when thread A unlocks and re-locks the mutex without thread B noticing it (because it didn't get scheduled in between). You can have inefficiencies if thread B needlessly blocks thread A once it obtained a lock on the mutex. If you implement it with a pair of mutexes, you can also get into a deadlock. And so on. In other words, using mutexes for this purpose is going to be tricky and will require quite a bit testing, not to mention that the solution will have a lot more overhead than the naive one-mutex solution.

The third issue is wake-up times. The time elapsed between one thread unlocking a mutex and another thread obtaining a lock on it (after waiting for it) is generally not guaranteed to be fast or even predictable (but you can generally have an upper-bound for it). In some applications, this can be a critical issue.

Currently, I'm using CreateEvent and SetEvent from WINAPI and I wanted a cross-platform way of doing so without doing #ifdef windows and ifdef linux, etc..

In Windows, you can use the CreateEvent / SetEvent mechanism instead of a mutex. But, from Windows Vista and up, a more efficient alternative is to use a condition variable. A condition variable is what Unix/Linux (POSIX) has always had as its main mechanism for this purpose, and their introduction into Windows has pretty much made events obsolete. The problem is that events are more or less a kernel-based implementation based on mutex-style (or critical sections) solution, for which a lot of the overhead arguments I made above still apply (to a lesser extent since it is kernel-based). Condition variables are different, very different, and much faster, with reliably small latency (time between the signal and the wake-up). Basically, when a thread waits for a condition variable, it is taken out of the task scheduler and set to be woken up immediately when the condition variable is set (signaled). In other words, when a thread signals the CV, it is immediately put to sleep (and its associated mutex is unlocked) and the waiting thread is immediately woken up (and its associated mutex is locked). In other words, the CPU time scheduled for thread A is given to thread B, immediately (with some fixed, but short, latency) and with atomic swapping of the mutex locks. When you understand that, you also understand why events are pale in comparison. MSDN provides an example of using condition variables that is a classic producer-consumer setup, much like what you are describing.

Now, since newer versions of Windows, and all implementations of POSIX must provide condition variables, it means that virtually all operating systems in existence have them. And thus, condition variables are available in the C++11 threading library, as std::condition_variable. This is what I recommend that you should use. I would imagine that, that any operating systems that does not have condition variables, the behavior is emulated otherwise (e.g., using events or a solution using mutexes / semaphores).

Other important synchronization mechanisms that you should look at are future / promises and the async() function. They rely on condition variables for the very common task of spitting out a result from one thread, to wake up another to process it.

commented: Great explanation of CVs Mike! +11

Ohhh I see!! But what I did not understand is how Application Two sees the condition variable from Application One :S

That is why I had used Events in the first place. Because I was able to name them and check for that specific event from another process/application because it is system-wide.

I understand using the condition variable in a single application with many threads but not too sure how to do it in two different applications.

I was reading here earlier and saw that it cannot be shared across processes: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682052(v=vs.85).aspx

So I'm stuck with events?

Can C++11's Mutexes be used for Inter-Process Communication? In other words, can it be used for shared memory and signalling an event?

C++11 does not have any inter-process functionality.

C++11 threading primitives (mutexes, atomics, etc) are just that - threading primitives. They know nothing about processes, and they are not a means of achieving inter-process communication. The IS makes no mention of processes or inter-process communication; the behaviour of C++11 objects when placed in trans-process shared memory is undefined.

I wanted a cross-platform way of doing so without doing #ifdef windows and ifdef linux, etc..

So I'm stuck with events?

No.
Boost.Interprocess http://www.boost.org/doc/libs/1_52_0/doc/html/interprocess.html
is portable across Windows and POSIX, and has a wide range of higher-level interprocess mechanisms.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.