7

We have 2 applications. One written in C# and the other in C++. We need to maintain a counter (in memory) shared between these processes. Every time one of these applications start, it needs to check for this counter and increase it and every time the application shut-down it needs to decrease the counter. If the application has a crash or shut-down using task manager, we also need the counter to decrease.
We thought of using one of the OS synchronization objects like MUTEX.
My question: What kind of sync object is the best for cross process (when one is C# and the other C++)

Hope my question was clear.
Thank you very much,

Adi Barda

Adi Barda
  • 3,259
  • 11
  • 32
  • 33
  • Is this in windows or multiple OS's? – Jon Cage Feb 02 '10 at 10:08
  • The main problem I see is that your requirement states that if the program crashes you'd like the value decremented. This would be reasonably difficult to achieve with any reliabilty. – ScaryAardvark Feb 02 '10 at 10:13
  • @Scary: If you catch all exceptions your ought to be able to still do the decrement. If you're killing the process you're stuck unless you change the value in memory when a process starts up and it doesn't crash between starting and changing the mutex... – Jon Cage Feb 02 '10 at 10:16
  • Jon: From MS documentation I understand that that I can use a Mutex for the use-case of application crash: "...If a thread terminates while owning a mutex, the mutex is said to be abandoned. The state of the mutex is set to signaled, and the next waiting thread gets ownership. Beginning in version 2.0 of the .NET Framework, an AbandonedMutexException is thrown in the next thread that acquires the abandoned mutex. Before version 2.0 of the .NET Framework, no exception was thrown..." – Adi Barda Feb 02 '10 at 11:09
  • @Jon. I wouldn't count catching all exceptions as a crash. That's an orderly shutdown. it may be an orderly shutdown in the face of something unexpected but it's still not a crash. Even installing "at_exit" handlers etc wouldn't help. The only thing you can do is create a wrapper process which monitors the status of the real process and if it crashes then you could decrement the counter.. But what happens if your wrapper process dies..... – ScaryAardvark Feb 02 '10 at 11:15
  • @Adi. Yes you can use a mutex to protect the shared counter but how do you know if it was decremented correctly in the face of a crash.. – ScaryAardvark Feb 02 '10 at 11:16
  • @Scary... so A pool of watching processes then; chances of them all going down at the same time is pretty slim right? ;-) – Jon Cage Feb 02 '10 at 11:42
  • @Jon. Yes, it's a vicious circle. As I pointed out. Who's watching the watchers :) – ScaryAardvark Feb 02 '10 at 18:04

3 Answers3

10

You might get away with named semaphore. Semaphore is basically a count, it is here to allow developers limit the number of thread/processes that are accessing some resource. Usually it works like that

  1. You create a semaphore with maximum count N.
  2. N threads call waiting function on it, WaitForSingleObject or similar and each of them go on without waiting. Each time internal semaphore counter goes down.
  3. N+1 thread also calls waiting function but because internal counter of our semaphore is 0 now, it has to wait.
  4. One of our first N threads releases the semaphore by calling ReleaseSemaphore function. This function increments internal counter of semaphore.
  5. Our waiting thread don't have to wait now, so it resumes but semaphore counter goes back to 0.

I don't think this is how you want to use it though. So, instead, you should:

  1. Create named semaphore with initial counter set to zero.
  2. When application start, immediately release it, increasing the counter. You'll get previous counter value during that call.
  3. When application ends, call WaitForSingleObject(hSemaphore, 0), decreasing the counter. 0 means you don't want to wait.

This is all quite easy.

In C++

//create semaphore
HANDLER hSemaphore = CreateSemaphore(NULL, 0, BIG_NUMBER, "My cool semaphore name");
//increase counter
LONG prev_counter;
ReleaseSemaphore(hSemaphore, 1, &prev_counter);
//decrease counter
WaitForSingleObject(hSemaphore, 0);

In C#

using System.Threading;
//create semaphore
Semaphore sem = new Semaphore(0, BIG_NUMBER, "My cool semaphore name");
//increase counter
int prev_counter = sem.Release(); 
//decrease counter
sem.WaitOne(0);

Names and BIG_NUMBERs should be the same obviously.

If this is not sufficient for your task, you will have to look into shared memory and lock access to it though named mutex, but that is a little bit more complicated.

vava
  • 24,851
  • 11
  • 64
  • 79
  • aren't semaphore suitable only for the same process? – Adi Barda Feb 02 '10 at 10:54
  • 2
    Events, mutexes, semaphores and times can have names which makes them accessible system wide. http://msdn.microsoft.com/en-us/library/ms684292%28VS.85%29.aspx – vava Feb 02 '10 at 11:27
  • Depending on your application protocols, you can use IPC of some sort to negotiate the named semaphore (in the unlikely event that what you choose is used by a different process) – C. Tewalt Jan 14 '16 at 22:15
1

Seems like you need a named semaphore (CreateSemaphore): http://msdn.microsoft.com/en-us/library/ms682438(VS.85).aspx for C++ which is suited for increment/decrement.

In C# you have the System.Threading.Semaphore class.

1

Have a look at this thread for methods to share some memory for synchronisation purposes or here for some suggestions for synchronising in .net/c#.

If there are .net methods available, they should work for both C++ and C#..

Community
  • 1
  • 1
Jon Cage
  • 36,366
  • 38
  • 137
  • 215