views:

519

answers:

5

I'm programming an interprocess communication module (Process A and Process B).

Is there any way the communication thread in B can run (be unlock) as soon as process A finishes a specific action, I mean without B doing any polling nor B waiting too much after A finishes its action?

Which are the concepts/models/design patterns governing these issues? (Something more precise than interprocess synchronization). Which libraries/methods do you recommend?

Thanks.

Edit: I'm looking for methods suitable for each of the three main OSes: Ms Windows, Apple Mac OS X, GNU/Linux.

A: 

If your OS supports signals you could unlock a mutex from a signal handler and send the signal from process A as soon as you finish the task.

Process B would be waiting on a mutex or other synchronization tool and A would be working on whatever, then when finishes sends signal USR1 for example, and USR1 handler in process B unlocks the corresponding synchronization tool.

Arkaitz Jimenez
It seems it is POSIX; have you seen that adapted to Windows?
moala
Not sure if you can use signals properly in Windows, but I know you have other choices, as windows events, haven't used them though.
Arkaitz Jimenez
No there no such thing as reliable posix signals on windows ...
neuro
A: 

The most common is to use select()/poll(). Both can check several file descriptors if there's input available. Both receive a timeout parameter - this will prevent busy wait, which may consume 100% CPU. This is very suitable solution for small/medium applications.

Another approach is to make polling in separate thread.

If you're going to develop a big application it's worth to look towards ACE framework or boost. These frameworks are cross platform solutions, well designed and well tested.

dimba
Thanks for your answer, but I meant "without B doing any polling". Maybe select() is more appropriate?
moala
The only way I can thing is signalling (signal() in Linux), but from my experience this solution is not appropriate for high load. On Linux signal will also abort system calls (EINTR error) which will unnecessary complicate your program. Calling select()/poll() with timeout zero, will just check if there's something to read. After that you can continue with other tasks.
dimba
No signals on windows ...
neuro
A: 

EDIT: I mistakenly thought you needed inter thread synchronizing, Revised for IPC

I think you need something like waitable events.

In Windows you can use CreateEvent(), to create (or get an existing) named, auto-reset event.

When process A completes processing, it should call SetEvent(), while process B should call WaitForSingleObject() to sleep until completion (or timeout).

Alternately, you can use semaphores created by CreateSemaphore(), initialized to 0. Process A signals completion by calling ReleaseSemaphore(), while process B again uses WaitForSingleObject() to wait for completion.

Under Linux and OS X you can use semaphores to a similar effect. use sem_open() to create a named semaphore, with 0 as its initial value.

When process A completes, it should call sem_post() to increment the semaphore, while process B should call sem_wait() to sleep until completion.

NOTE: the semaphore method may allow multiple completions to be signaled, you should handle this by setting a maximum count under Windows, or checking the current sem value for sanity with sem_getvalue()


I think condition variables fit what you're trying to do, here's a sample that would work on Linux and OSX

#include <pthread.h>
/* no error checking, quick and dirty sample */
pthread_mutex_t g_mutex;
pthread_cond_t g_cond;
int a_done = 0;

void init(void)
{
    pthread_mutex_init(&g_mutex, NULL);
    pthread_cond_init(&g_cond, NULL);
}

void thread_a(void *arg)
{
    /* do something here... */
    pthread_mutex_lock(&g_mutex);
    a_done = 1;
    pthread_cond_signal(&g_cond);
    pthread_mutex_unlock(&g_mutex);
}

void thread_b(void *arg)
{
    /* wait for a to complete */
    pthread_mutex_lock(&g_mutex);
    while (!a_done)
        pthread_cond_wait(&g_cond, &g_mutex);
    a_done = 0;
    pthread_mutex_unlock(&g_mutex);
}

Under Windows, you can use pthreads-win32, or native condition variables under Vista, see the MSDN Condition Variables page for more information.

References:

Hasturkun
The answer does not handle the inter process part. I have not used intensively pthread-win32, check the compatibility issues
neuro
ah, I read this as an inter-thread issue. I'll revise the answer later
Hasturkun
A: 

Well, in my opinion and experience, the best way to do that in a portable and simple way is to use sockets. Plus you get the possibility to have the two processes on different machine (if needed). Plus you can extand the communication to handle more than synchro.

If you don't want to poll, use a thread that wait for a synchro message on a socket. You read the socket in a blocking way. When you receive the message you use a standard multithread synchronisation to handle your synchronisation. In your case as B should wait till A ends, you just have to read in a blocking way in your process.

To be portable use a portable socket library like boost or ptypes or whatever.

neuro
+2  A: 

This is quite hard job:

For Unix OSes you can use:

  • pthread condition and mutex with setpshared argument.

    Note: it is supported well under Linux 2.6, Solaris, but it does not supported FreeBSD and Cygwin (don't know about Mac OS X)

  • For Unixes you may also use named semaphores, but I don't know the support level of them

  • For Windows there are some events...

This is hard job, especially for IPC...

So if you want something portable, I'd suggest to take a look on Boost.Interprocess that has conditions and mutexes...

But make sure that all feature supported on all OSes you want to support.

Things you should note about Boost.Interprocess

Check carefully level of support for each Unix OS you need to work with, because Boost.Interprosess uses pthread_* functions that are not always supported... and then fails back to emulation -- check the quality of such emulation

Also, check how this stuff works on Windows -- as far as I know that there is no "in-shared-memory" mutexes in Win32 API, generally named objects should be used, so check what is supported and how.

Artyom
It just misses an additional mention to boost::interprocess::interprocess_semaphore
moala