Using the related Windows event functions for thread synchronization
// For WinXp as a target, change appropriately
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
#define NUMTHREADS 4
HANDLE hGlobalWriteEvent;
HANDLE hReadEvents[NUMTHREADS], hThread;
DWORD i, IDThread;
void ThreadFunction(LPVOID lpParam)
{
DWORD dwWaitResult;
HANDLE hEvents[2];
hEvents[0] = *(HANDLE*)lpParam; // thread's read event
hEvents[1] = hGlobalWriteEvent;
dwWaitResult = WaitForMultipleObjects(
2, // number of handles in array
hEvents, // array of event handles
TRUE, // wait till all are signaled
INFINITE); // indefinite wait
printf("\nIn ThreadFunction()...\n");
switch (dwWaitResult)
{
// Both event objects were signaled.
case WAIT_OBJECT_0:
printf("Both event objects were signaled.\n");
// Read from the shared buffer...
break;
// An error occurred.
default:
printf("Wait error: %d\n", GetLastError());
ExitThread(0);
}
// Set the read event to signaled.
if (!SetEvent(hEvents[0]))
{
printf("SetEvent(), setting the read event to signaled failed.\n");
// Error exit.
}
else
printf("SetEvent(), setting the read event to signaled is OK.\n");
}
// ====================================
void WriteToBuffer(void)
{
DWORD dwWaitResult, i;
printf("\nIn WriteToBuffer()...\n");
// Reset hGlobalWriteEvent to non-signaled, to block readers...
if (!ResetEvent(hGlobalWriteEvent))
{
printf("ResetEvent(hGlobalWriteEvent) failed.\n");
// Error exit.
}
else
printf("ResetEvent(hGlobalWriteEvent) is OK.\n");
// Wait for all reading threads to finish reading...
dwWaitResult = WaitForMultipleObjects(
NUMTHREADS, // number of handles in array
hReadEvents, // array of read-event handles
TRUE, // wait until all are signaled
INFINITE); // indefinite wait
switch (dwWaitResult)
{
// All read-event objects were signaled...
case WAIT_OBJECT_0:
printf("All read-event objects were signaled.\n");
// Write to the shared buffer...
break;
// An error occurred...
default:
printf("Wait error: %d\n", GetLastError());
ExitProcess(0);
}
// Set hGlobalWriteEvent to signaled...
if (!SetEvent(hGlobalWriteEvent))
{
// Error exit.
}
// Set all read events to signaled...
for (i = 0; i < NUMTHREADS; i++)
{
if (!SetEvent(hReadEvents[i]))
{
printf("SetEvent(), setting read event %d to signaled failed.\n", i);
// Error exit.
}
else
printf("SetEvent(), read event %d signaled.\n", i);
}
}
// =======================================
void CreateEventsAndThreads(void)
{
// Create a manual-reset event object. The master thread sets this to non-signaled when it writes to the shared buffer...
printf("In CreateEventsAndThreads()...\n");
hGlobalWriteEvent = CreateEvent(
NULL, // no security attributes
TRUE, // manual-reset event
TRUE, // initial state is signaled
L"MasterThWriteEvent" // object name
);
if (hGlobalWriteEvent == NULL)
{
printf("CreateEvent() failed, error: %d.\n", GetLastError());
// error exit...
}
else
printf("CreateEvent(), master thread with manual reset is OK.\n\n");
// Create multiple threads and an auto-reset event object for each thread. Each thread sets its event object to
// signaled when it is not reading from the shared buffer...
printf("Multiple threads with auto-reset event object for each thread...\n");
for (i = 0; i < NUMTHREADS; i++)
{
// Create the auto-reset event.
hReadEvents[i] = CreateEvent(
NULL, // no security attributes
FALSE, // auto-reset event
TRUE, // initial state is signaled
NULL); // object not named
if (hReadEvents[i] == NULL)
{
printf("CreateEvent() failed.\n");
// Error exit.
}
else
printf("CreateEvent() #%d is OK.\n", i);
hThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) ThreadFunction,
&hReadEvents[i], // pass event handle
0, &IDThread);
if (hThread == NULL)
{
// Error exit.
printf("CreateThread() failed, error: %d.\n", GetLastError());
}
else
printf("CreateThread() #%d is OK.\n\n", i);
}
}
int main(void)
{
CreateEventsAndThreads();
WriteToBuffer();
return 0;
}
Output example:
In CreateEventsAndThreads()...
CreateEvent(), master thread with manual reset is OK.
Multiple threads with auto-reset event object for each thread...
CreateEvent() #0 is OK.
CreateThread() #0 is OK.
CreateEvent() #1 is OK.
CreateThread() #1 is OK.
CreateEvent() #2 is OK.
CreateThread() #2 is OK.
CreateEvent() #3 is OK.
CreateThread() #3 is OK.
In WriteToBuffer()...
ResetEvent(hGlobalWriteEvent) is OK.
All read-event objects were signaled.
SetEvent(), read event 0 signaled.
SetEvent(), read event 1 signaled.
SetEvent(), read event 2 signaled.
SetEvent(), read event 3 signaled.
In ThreadFunction()...
Both event objects were signaled.
SetEvent(), setting the read event to signaled is OK.
In ThreadFunction()...
Both event objects were signaled.
SetEvent(), setting the read event to signaled is OK.
In ThreadFunction()...
In ThreadFunction()...
Both event objects were signaled.
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 - How to
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 related event functions for Windows thread synchronization
To show: The Windows process and thread related functions used in thread synchronization