Mutexes with win32

A mutex is a win32 kernel object that enables any thread in the system to acquire mutually exclusive ownership of a resource. A mutex can therefore be used to synchronize access to a resource between threads belonging to different processes.

Mutexes are created with the CreateMutex() function. The CreateMutex() function takes three parameters. The first parameter is a pointer to a SECURITY_ATTRIBUTES structure; if NULL, the mutex is created with default security attributes. The second argument is a Boolean flag indicating whether or not the calling thread is to own the mutex after returning from the function. The third and final argument is a null terminated string specifying the name of the mutex object. Passing NULL here will create a mutex with no name, which are only visible to threads within the process that created the mutex.

#include "stdafx.h"
#include <Windows.h>

int main()
{
 HANDLE hMutex = CreateMutex(NULL, TRUE, "MutexExample");

 if (hMutex == NULL) {
 printf("Error creating mutex.\n");
 exit(EXIT_FAILURE);
 }

 if (GetLastError() == ERROR_ALREADY_EXISTS) {
 //the mutex already is in existence
 printf("The mutex alread exists.\n");
 exit(EXIT_FAILURE);
 }
 else {
 printf("Mutex created.\n");
 printf("...releasing mutex.\n");
 //release ownership of the mutex
 ReleaseMutex(hMutex);
 }

 //close mutex handle
 CloseHandle(hMutex);

 return 0;
}

Note that to close the handle to a mutex, we use the CloseHandle() function.

If we want to get a handle to a mutex that has been previously created by another thread either in the same or in a different process, we can use the OpenMutex() function. The OpenMutex() function, like the CreateMutex() function, has three parameters.

The first parameter is a DWORD value indicating a bitfield flag that specifies the type of access the calling thread would like to have to the mutex named in the third parameter. The second argument is a Boolean value indicating whether or not the returned handle can be inherited by processes created when the calling process using the CreateProcess() function. The value NULL is returned to indicate failure.

 #include "stdafx.h"
#include <Windows.h>

int main()
{
 HANDLE hMutexOne, hMutexTwo;
 TCHAR *tszMutexName = _T("AnExmpMutex");

 hMutexOne = CreateMutex(NULL, TRUE, tszMutexName);

 if (hMutexOne == NULL) {
 printf("Unable to create mutex.\n");
 printf("Error no. %d\n", GetLastError());
 exit(EXIT_FAILURE);
 }

 if (GetLastError() == ERROR_ALREADY_EXISTS) {
 printf("Error! Handle already exists.\n");
 exit(EXIT_FAILURE);
 }

 printf("Mutex created!\n");

 hMutexTwo = OpenMutex(MUTEX_ALL_ACCESS, TRUE, tszMutexName);

 if (hMutexTwo == NULL) {
 printf("Unable to open mutex.\n");
 exit(EXIT_FAILURE);
 }
 else {
 printf("Mutex opened.\n");
 printf("Releasing opened mutex.\n");
 ReleaseMutex(hMutexTwo);
 }


 printf("Releasing created mutex.\n");
 ReleaseMutex(hMutexOne);

 printf("Closing handles.\n");
 CloseHandle(hMutexOne);
 CloseHandle(hMutexTwo);

 return 0;
}

Note that the OpenMutex() function does not attempt to acquire ownership of the mutex.

A mutex can be in one of two states: signaled or nonsignaled. A mutex is in the signaled state when no thread owns the mutex. Threads take ownership of mutexes via the OpenMutex() or CreateMutex() functions.

Ownership of a mutex is released by a call to the ReleaseMutex() function, which only has one parameter, the handle to the mutex to be released.

#include "stdafx.h"
#include <Windows.h>

const int Num_Threads = 5;
DWORD WINAPI ChildThreadFunc(LPVOID lpMutex);

int main()
{
 int i = 0;
 DWORD dwNewThreadID;
 HANDLE hChildThreads[Num_Threads];
 //create mutext with this thread the owner of the mutex
 HANDLE hMutex = CreateMutex(NULL, TRUE, NULL);

 while (i < Num_Threads) {
 hChildThreads[i] = CreateThread(NULL, NULL, &ChildThreadFunc, (void*)hMutex, 0, &dwNewThreadID);
 printf("In parent thread, child thread ID %p created.\n", dwNewThreadID);
 i++;
 }

 printf("In parent thread, releasing mutex.\n");
 ReleaseMutex(hMutex);

 Sleep(6000);

 return 0;
}

DWORD WINAPI ChildThreadFunc(LPVOID lpMutex) {
 //convert parameter to mutex handle
 HANDLE hMutex = (HANDLE)lpMutex;
 //save the thread ID
 DWORD dwThreadID = GetCurrentThreadId();
 DWORD dwResult = WaitForSingleObject(hMutex, INFINITE);
 if (dwResult == WAIT_OBJECT_0) {
 printf("Thread %p acquired mutex.\n", dwThreadID);
 //hold the mutex
 Sleep(1000);
 printf("Thread %p releasing the mutex.\n", dwThreadID);
 ReleaseMutex(hMutex);
 }
 else {
 return 1;
 }
 return 0;
}

Note that only one thread ever owns a mutex at a given time.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s