Using the semaphore object for thread synchronization

 

 

 

/* The following example uses a semaphore object to limit the number of threads that can perform a particular task.

First, it uses the CreateSemaphore() function to create the semaphore and to specify initial and maximum counts,

then it uses the CreateThread() function to create the threads. Before a thread attempts to perform the task,

it uses the WaitForSingleObject() function to determine whether the semaphore's current count permits it to do so.

The wait function's time-out parameter is set to zero, so the function returns immediately if the semaphore is in

the nonsignaled state. WaitForSingleObject() decrements the semaphore's count by one. When a thread completes the task,

it uses the ReleaseSemaphore() function to increment the semaphore's count, thus enabling another waiting thread to

perform the task.

*/

// For WinXp as a target, change appropriately

#define _WIN32_WINNT 0x0501

 

#include <windows.h>

#include <stdio.h>

#define MAX_SEM_COUNT 4

#define THREADCOUNT 6

 

// Handle to semaphore object

HANDLE ghSemaphore;

// Task counting

static int count = 0;

 

// Create thread function

DWORD WINAPI ThreadProc(LPVOID);

 

int wmain(void)

{

HANDLE aThread[THREADCOUNT];

DWORD ThreadID;

int i;

// Create a semaphore with initial and max counts of MAX_SEM_COUNT

ghSemaphore = CreateSemaphore(

NULL, // default security attributes

MAX_SEM_COUNT, // initial count

MAX_SEM_COUNT, // maximum count

NULL); // unnamed semaphore

 

if (ghSemaphore == NULL)

{

wprintf(L"CreateSemaphore()failed, error: %d\n", GetLastError());

return 1;

}

else

wprintf(L"CreateSemaphore() should be fine!\n");

 

// Create worker threads

for( i=0; i < THREADCOUNT; i++ )

{

aThread[i] = CreateThread(

NULL, // default security attributes

0, // default stack size

(LPTHREAD_START_ROUTINE) ThreadProc,

NULL, // no thread function arguments

0, // default creation flags

&ThreadID); // receive thread identifier

 

if(aThread[i] == NULL)

{

wprintf(L"CreateThread() failed, error: %d\n", GetLastError());

return 1;

}

else

wprintf(L"CreateThread() looks OK!\n");

}

 

// Wait for all threads to terminate

wprintf(L"Waiting all threads to terminate...\n");

WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

 

// Close thread and semaphore handles

wprintf(L"Closing all the thread and semaphore handles...\n");

 

for( i=0; i < THREADCOUNT; i++ )

CloseHandle(aThread[i]);

CloseHandle(ghSemaphore);

return 0;

}

 

DWORD WINAPI ThreadProc( LPVOID lpParam )

{

// lpParam not used in this example

UNREFERENCED_PARAMETER(lpParam);

DWORD dwWaitResult;

BOOL bContinue=TRUE;

 

while(bContinue)

{

// Try to enter the semaphore gate.

dwWaitResult = WaitForSingleObject(

ghSemaphore, // handle to semaphore

0L); // zero-second time-out interval

switch (dwWaitResult)

{

// The semaphore object was signaled.

case WAIT_OBJECT_0:

{

// TODO: Perform task

wprintf(L"Thread %d: wait succeeded...\n", GetCurrentThreadId());

bContinue=FALSE;

// Simulate thread spending time on task

wprintf(L"Completing task #%d....\n", count++);

Sleep(5);

// Release the semaphore when task is finished

if (!ReleaseSemaphore(

ghSemaphore, // handle to semaphore

1, // increase count by one

NULL) ) // not interested in previous count

{

wprintf(L"ReleaseSemaphore() failed, error: %d\n", GetLastError());

}

else

wprintf(L"ReleaseSemaphore() is pretty fine!\n");

}

break;

 

// The semaphore was nonsignaled, so a time-out occurred.

case WAIT_TIMEOUT:

wprintf(L"Thread %d: wait timed out...\n", GetCurrentThreadId());

break;

}

}

return TRUE;

}

 

Output example:

 

CreateSemaphore() should be fine!

CreateThread() looks OK!

Thread 636: wait succeeded...

CreateThread() looks OK!

Completing task #0....

CreateThread() looks OK!

Thread 4952: wait succeeded...

Completing task #1....

CreateThread() looks OK!

Thread 4944: wait succeeded...

Completing task #2....

CreateThread() looks OK!

Thread 5200: wait succeeded...

Thread 5460: wait timed out...

CreateThread() looks OK!

Completing task #3....

Thread 5460: wait timed out...

Waiting all threads to terminate...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

 

[TRIMMED]

 

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

 

[TRIMMED]

 

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

 

 

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 5460: wait timed out...

Thread 2448: wait timed out...

Thread 2448: wait timed out...

ReleaseSemaphore() is pretty fine!

ReleaseSemaphore() is pretty fine!

ReleaseSemaphore() is pretty fine!

ReleaseSemaphore() is pretty fine!

Thread 5460: wait timed out...

Thread 5460: wait succeeded...

Thread 2448: wait succeeded...

Completing task #4....

Completing task #5....

ReleaseSemaphore() is pretty fine!

ReleaseSemaphore() is pretty fine!

Closing all the thread and semaphore handles...

 

 

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 semaphore for thread synchronization

To show: The Windows process and thread related functions

 

 

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