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

 

 

C and C++ Programming Resources | C & C++ Code Example Index