Using the Windows mutex object related functions for thread synchronization
// For WinXp as a target, change appropriately
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
// Number of thread
#define THREADCOUNT 2
// Global var
HANDLE ghMutex;
// Simulated function
DWORD WINAPI WriteToDatabase(LPVOID);
int wmain( void )
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
// Create a mutex with no initial owner
ghMutex = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (ghMutex == NULL)
{
wprintf(L"CreateMutex() error %d\n", GetLastError());
return 1;
}
else
wprintf(L"Unnamed mutex object successfully created!\n");
// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) WriteToDatabase,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
if( aThread[i] == NULL )
{
wprintf(L"CreateThread() error %d\n", GetLastError());
return 1;
}
else
wprintf(L"CreatThread() is OK. Thread #%d, ID: %d was successfully created!\n", i, GetCurrentThreadId());
}
wprintf(L"\n");
// Wait for all threads to terminate
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread and mutex handles
for( i=0; i < THREADCOUNT; i++ )
{
if(CloseHandle(aThread[i]) != 0)
wprintf(L"Thread #%d handle with ID: %d was successfully closed!\n", i, GetCurrentThreadId());
else
wprintf(L"Failed to close thread #%d handle, error %d!\n", i, GetLastError());
}
if(CloseHandle(ghMutex) != 0)
wprintf(L"Mutex object handle was successfully closed!\n", i);
else
wprintf(L"Failed to close mutex object handle, error %d!\n", i, GetLastError());
return 0;
}
DWORD WINAPI WriteToDatabase(LPVOID lpParam)
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwCount=0, dwWaitResult;
// Request ownership of mutex
while( dwCount < 10 )
{
dwWaitResult = WaitForSingleObject(
ghMutex, // handle to mutex
INFINITE); // no time-out interval
switch (dwWaitResult)
{
// The thread got ownership of the mutex
case WAIT_OBJECT_0:
__try {
// TODO: Write to the database
wprintf(L"Thread %d writing to database...\n", GetCurrentThreadId());
dwCount++;
}
__finally {
// Release ownership of the mutex object
if (!ReleaseMutex(ghMutex))
{
// Handle error.
wprintf(L" ReleaseMutex() error %d\n", GetLastError());
}
else
wprintf(L" ReleaseMutex() - Handle to mutex object was released!\n");
}
break;
// The thread got ownership of an abandoned mutex. The database is in an indeterminate state
case WAIT_ABANDONED:
{
wprintf(L"WAIT_ABANDONED...\n");
return FALSE;
}
}
}
return TRUE;
}
Output example:
Unnamed mutex object successfully created!
CreatThread() is OK. Thread #0, ID: 3144 was successfully created!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
CreatThread() is OK. Thread #1, ID: 3144 was successfully created!
ReleaseMutex() - Handle to mutex object was released!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 484 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread 2516 writing to database...
ReleaseMutex() - Handle to mutex object was released!
Thread #0 handle with ID: 3144 was successfully closed!
Thread #1 handle with ID: 3144 was successfully closed!
Mutex object handle was successfully closed!
Press any key to continue . . .
Compiler: Visual C++ Express Edition 2005
Compiled on Platform: Windows XP Pro SP2
Target platform: none, just for learning and fun
Header file: Standard and Windows
Additional library: Windows Platform SDK
Additional project setting: Set project to be compiled as C
Project -> your_project_name Properties -> Configuration Properties -> C/C++ -> Advanced -> Compiled As: Compiled as C Code (/TC)
Other info: non-CLR or unmanaged
To do: Using the Windows mutex object and related functions for thread synchronization
To show: The Windows process and thread related functions manipulation - using mutex object