Click here to Skip to main content
15,885,943 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi
I have a problem trying to synchronise many clients with one server via a mutex. Ultimately I am aiming to pass data through shared memory from the clients and then wake a console application written in C++ to process the new data. I have a simple example here where I am just trying to count how many times I wake the console application but it is not working:

Server application lives in a constant loop but waiting to be woken up, it creates the mutex and events and so is always run first:

int main()
	
	int int_count = 0;
	DWORD d_wait_res, d_wait_err;
	HANDLE event_handle_console_wake = CreateEvent(NULL,TRUE,FALSE,TEXT("Console_Wake"));
	HANDLE event_handle_console_sleep = CreateEvent(NULL,TRUE,FALSE,TEXT("Console_Sleep"));
	HANDLE mutex_console_access = CreateMutex(NULL,FALSE,TEXT("Mutex_Console_Access"));
	while(1)
	{
		d_wait_res = WaitForSingleObject(event_handle_console_wake,INFINITE);
		d_wait_err = GetLastError();
		ResetEvent(event_handle_console_wake);
		int_count++;
		cout << int_count << " has arrived" << endl << endl;
		SetEvent(event_handle_console_sleep);
	}
	
	return 0;
}


The clients call a DLL function called WakeConsole()

int My_Shared_Memory::WakeConsole()
{
	
	DWORD d_wait_result, d_wait_error;
	DWORD d_wait_mutex, d_release_mutex;
	
	event_handle_wake_console_from_dll = OpenEvent(EVENT_MODIFY_STATE,FALSE,TEXT("Console_Wake"));
	event_handle_console_finished = OpenEvent(EVENT_ALL_ACCESS,FALSE,TEXT("Console_Sleep"));
	mutex_console_access = OpenMutex(SYNCHRONIZE,FALSE,TEXT("Mutex_Console_Access"));
		
	d_wait_mutex = WaitForSingleObject(mutex_console_access,INFINITE);
		
	SetEvent(event_handle_wake_console_from_dll);
	d_wait_result = WaitForSingleObject(event_handle_console_finished,INFINITE);
	d_wait_error = GetLastError();
	ResetEvent(event_handle_console_finished);
	
	d_release_mutex = ReleaseMutex(mutex_console_access);
		
	CloseHandle(mutex_console_access);
	CloseHandle(event_handle_wake_console_from_dll);
	CloseHandle(event_handle_console_finished);
	return 0;
		
}


As you can probably work out, the clients call the WakeConsole() function and then this function waits for access to the mutex and then wakes up the console by use of signaling the event the console is waiting for. The console runs and simply adds one to a counter and then signals an event so that the WakeConsole() function can continue where it left off. The problem I am having is that my clients are calling WakeConsole() many times and the counter within my console lags behind and does not seem to count all my calls. I would have hoped that when a client calls WakeConsole() then it would sit and wait for the mutex to be available and so could not be missed?

I have tried many things to work out what is going on and tried to give the simplest example of something which does not work that I feel should. I just need help or pointers in how to debug this thoroughly or maybe I have missed the point with mutexes and events completely?

Please ask questions as I have probably not explained this as thoroughly as I might.

Thanks for reading

Mark
Posted

Take a look at this article:
Patterns for Concurrent, Parallel, and Distributed Systems[^]

After a wee bit of reading you'll be able to solve this elegantly and efficiently using the reactor pattern - you'll probably also end up using ACE[^].

Best regards
Espen Harlinn
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 15-Mar-11 19:06pm    
Yes, good as a general source and... ACE again!
A 5.
--SA
Espen Harlinn 15-Mar-11 19:30pm    
Thanks SAKryukov!
Mark Briscombe 16-Mar-11 10:15am    
Thanks Espen, what you have suggested I read looks very helpful!
Espen Harlinn 16-Mar-11 13:27pm    
Great, thanks for the vote :)
I feel you're confused. You're trying to work with Mutex where Event should be used. Here is the idea: AwakeOfSomething should be just a call to SetEvent, next operation depends on the Event option (manualReset or not), so you many need ResetEvent or not.

The Mutex is a very different beast. You should limit it application to only one: mutual exclusion (very informative phrase, isn't it :-)?). As a rule of thumb, you need a mutex per each shared data structure (not a formal structure, but some set of object supposed to keep atomicity). Every access of such structure should be sandwiched be a mutex. You can nest mutexed block, but guarantee it is always releases. For this purpose, you need to put all you do after taking a mutex in "try" block and release a mutex always in "finally" block. If you always work through a process boundary, your mutexed data is in the Shared Data.

Mutexes and Events should not intercept functionality. Also, you data can effectively be serialized be Events along. You need to calculate very accurately if the Mutexes are redundant or not. In difficult case, use Petri net formalism.

Now, I don't know exactly if you exchange data between you components. Chances are, you need a blocking data queue. I can give you an idea how it works (via Event objects which are called EventWaitHandle in .NET). Sorry my CodeProject code is in C#, it will give your an idea anyway: Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

Now, for the transport part you can use named pipes, because you work through the process boundary. In this case, don't use Shared Memory, use pipes instead.

Finally, there is a secret weapon which can replace both. This is Socket API! Did you know they were originally designed as the IPC for the same machine, even before IP was used. You still can use sockets on a single machine as just an IPC tool. This thing in my favorite.

It was just a skeleton. I cannot go in further detail right now, because I don't know you application detail to offer the only solution. By the same reason I don't go into API references: you can find it all by my keywords. You're welcome to ask follow-up Questions (please, don't post them as Answers, a common and annoying mistake!), especially if you provide more information and explain your ultimate goals.

—SA
 
Share this answer
 
Comments
Espen Harlinn 15-Mar-11 18:37pm    
Another good reply - 5ed!
Sergey Alexandrovich Kryukov 15-Mar-11 19:07pm    
Thank you.
Well, just a skeleton, let's see what OP says...
--SA
Mark Briscombe 16-Mar-11 10:20am    
Also thank you for your answer SAKryukov, I see what you are saying about events and mutexes especially about using a try-finally block to ensure a release anytime I use one. Also I will definitely look into what you suggest regarding Sockets. I have some reading to do! Thanks again.
Sergey Alexandrovich Kryukov 16-Mar-11 16:31pm    
Hope you will end up with clear robust design which is quite feasible through some hard work.
Good luck, thank you for accepting my Answer; call again.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900