Windows Thread Synchronization 22

 

 

 

 

 

Using Semaphore Objects Program Example

 

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.

Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.

 

Using Semaphore Objects Program Example: Creating new console application project of the Win32 C++

 

Then, add the source file and give it a suitable name.

 

Using Semaphore Objects Program Example: Adding new C++ source file to the existing project

 

Next, add the following source code.

 

#include <windows.h>

#include <stdio.h>

 

#define MAX_SEM_COUNT 10

#define THREADCOUNT 12

 

HANDLE ghSemaphore;

 

DWORD WINAPI ThreadProc(LPVOID);

 

void wmain()

{

    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() error %d\n", GetLastError());

        return;

    }

      else

            wprintf(L"CreateSemaphore() is OK\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() error %d\n", GetLastError());

            return;

        }

            else

                  wprintf(L"Thread %d with ID %d was created...\n", i, ThreadID);

    }

 

    // Wait for all threads to terminate

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

    WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

 

    // Close thread and semaphore handles

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

      {

            if(CloseHandle(aThread[i]) != 0)

                  wprintf(L"Handle to thread %i was closed!\n", i);

            else

                  wprintf(L"Failed to close the thread %i handle, error %d\n", i, GetLastError());

      }

   

      if(CloseHandle(ghSemaphore) != 0)

            wprintf(L"Handle to Semaphore object was closed!\n", i);

      else

            wprintf(L"Failed to close the Semaphore object handle, error %d\n", GetLastError());

 

}

 

DWORD WINAPI ThreadProc(LPVOID 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

                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 error %d\n", GetLastError());

                }

                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;

}

 

Build and run the project. The following screenshots are the sample outputs.

 

Using Semaphore Objects Program Example: A sample of console program output

 

Using Semaphore Objects Program Example: Another sample console program output

 

 

 

 

< Thread Synchronization 21 | Thread Synchronization Programming | Win32 Programming | Thread Synchronization 23 >