File:  [WindowsNT SDKs] / q_a / samples / semaphor / sema.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:29:42 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-nov-1993, ntsdk-jul-1993, HEAD
Microsoft Windows NT Build 511 (SDK Final Release) 07-24-1993

/*************************************************************************\
*  PROGRAM: Sema.c
*
*  PURPOSE:
*
*     To demonstrate controlling multiple threads through the use of a
*     semaphore.
*
*  FUNCTIONS:
*
*    WinMain()      - Initializes the window, and process the message loop.
*    MainWndProc()  - Process messages, creates semaphore and threads.
*
*  GLOBAL VARIABLES:
*
*    - hWnd:  Handle to the window.
*    - hSemaphore:
*             Handle of the semaphore used between the threads.
*
*  COMMENTS:
*
*    To Use:
*      Start the application.  You will see five rectangles: a dynamic
*      rectangle in the center (always changing color), and four static
*      rectangles surrounding it.  Each of the four rectagles has their
*      own color: red, blue, green, and gray.  The one in the center
*      alternates between these colors.
*
*      The four static rectangles represent four threads.  These four
*      threads compete for the rectangle in the middle, and their access
*      is controlled by the semaphore.  When the thread gains control of
*      the semaphore, it gets to draw it's color in the center rectangle.
*      (note: the threads do not actually draw any of the four static
*      rectangles.  To make the code simpler this is handled in the
*      WM_PAINT message in the MainWndProc().  They are only meant as
*      a visual representation of the threads.  The threads do however
*      draw the rectangle in the center with their specific color.)
*
*    What Happens:
*      The semaphore has a use count.  When it is set to zero, any thread
*      can access the semaphore and execute the code within its "semaphore
*      gate" by using WaitForSingleObject().  When the thread gains
*      control of the semaphore usint this call, the use count is
*      incremented by one.  When the thread is done executing its code,
*      it can call ReleaseSemaphore().  This will decrement the count
*      by what ever value you indicate (this code uses 1) signalling
*      to any other thread that it may gain control of the semaphore.
*
*      Note that any thread which has access to the semaphore may decrement
*      its use count with ReleaseSemaphore(); the thread does not have
*      to have control of the semaphore at the time.
*
*      In this code, the WM_CREATE message in MainWndProc creates a
*      semaphore.  The four threads are then created, each waiting
*      on the semaphore .
*
*      Each of the threads loop, blocking on a WaitForSingleObject()
*      call.  Once any thread has set the use count to 0, the thread
*      gets to draw draw the center rectagle with its color, and then
*      sleeps for half a second before freeing the semaphore again.
*      The thread then runs through the loop again.
*
\*************************************************************************/
#include <windows.h>
#include <stdlib.h>
#include "sema.h"


HANDLE hInst;
HANDLE hWnd;
HANDLE hSemaphore;

/*************************************************************************\
*
*  FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
*
*  PURPOSE: calls initialization function, processes message loop
*
*  COMMENTS:
*
\*************************************************************************/
int APIENTRY WinMain (HANDLE hInstance,
                      HANDLE hPrevInstance,
                      LPSTR  lpCmdLine,
                      int    nCmdShow)
{
  MSG  msg;
  WNDCLASS wc;

  UNREFERENCED_PARAMETER( lpCmdLine );
  UNREFERENCED_PARAMETER( hPrevInstance );

  hInst = hInstance;

  wc.style = CS_VREDRAW | CS_HREDRAW;
  wc.lpfnWndProc = (WNDPROC)MainWndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
  wc.hCursor = LoadCursor (NULL, IDC_ARROW);
  wc.hbrBackground = GetStockObject (WHITE_BRUSH);
  wc.lpszMenuName = "";
  wc.lpszClassName = "SemaWClass";

  RegisterClass(&wc);


  hWnd = CreateWindow ("SemaWClass",
                       "Semaphore Sample",
                       WS_OVERLAPPEDWINDOW,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       CW_USEDEFAULT,
                       NULL,
                       NULL,
                       hInstance,
                       NULL);


  ShowWindow(hWnd, nCmdShow);
  while (GetMessage (&msg, NULL, 0, 0))
    DispatchMessage (&msg);   // Dispatch message to window.

  return (msg.wParam);           // Returns value from PostQuitMessage.

}

/*************************************************************************\
*
*  FUNCTION:  MainWndProc (HWND, UINT, UINT, LONG)
*
*  PURPOSE:   To process the windows messages.  This procedure creates
*             the semaphore and the four threads.  It also draws the
*             four static rectangles.
*
*  VARIABLES USED:
*
*    - hThread?:
*             These four static varaibles are handles to the four
*             created threads.
*
*    - ThreadID?:
*             These four variables are local DWORDS used in the
*             CreateThread() call.
*
*    - pColor?:
*             These four variables are used as pointers to memory
*             which is allocated and filled with color values to
*             pass as a parameter to each of the threads (so the
*             threads know what color they are to paint the rectangle).
*
*    - Paint: A paint structure used in BeginPaint() and EndPaint().
*
*    - rect:  A RECT structure used to get the windows client area.
*             It's needed to figure out the new relative positions
*             of the four static rectangles when the user resizes
*             the window.
*
*    - Col?, Row?, width, height:
*             These local DWORDs are used to position the four static
*             rectangles and to determin their size.
*
*    - hDC:   Handle to the DC for the window.
*
*    - hBrush:
*             Handle to a brush, used to set the color of the four static
*             rectangles.
*
*  MESSAGES:
*
*    WM_CREATE:      - Creates a semaphore; allocates some
*                      memory and sets it with color values to be passed
*                      as parameter values to the threads.  It then
*                      creates four threads, giving each its own color.
*
*    WM_PAINT:       - Checks the size of the client space and then
*                      draws the four static rectangles to their relative
*                      positions.
*
*    WM_DESTROY:     - Terminates the threads, and posts a quit message.
*
*  CALLED BY:
*
*    WinMain();
*
*  CALLS TO:
*
*    ThreadProc();
*
\*************************************************************************/


LONG APIENTRY MainWndProc (HWND hwnd,
                           UINT message,
                           UINT wParam,
                           LONG lParam)
{
  DWORD  ThreadID1, ThreadID2, ThreadID3, ThreadID4;
  RECT   rect;
  DWORD  Col1, Col2, Col3, Row1, Row2, Row3, width, height;
  HDC    hDC;
  HANDLE hBrush;
  PAINTSTRUCT Paint;
  static HANDLE hThread1, hThread2, hThread3, hThread4;
  static DWORD  *pColor1,  *pColor2,  *pColor3,  *pColor4;
  CHAR Buf[80];


  switch (message)
      {

        case WM_PAINT:
          hDC = BeginPaint (hwnd, &Paint);
          GetClientRect( hWnd, &rect);       // Get window rectangle.

          width =  rect.right / 4;           // Calculate static rectangle's
          height = rect.bottom / 4;          // width and height.

          Col1 = (rect.right / 16)  * 1;     // Calculate x positions.
          Col2 = (rect.right / 16)  * 6;
          Col3 = (rect.right / 16)  * 11;
                                             // Calculate y positions.
          Row1 = (rect.bottom / 16) * 1;
          Row2 = (rect.bottom / 16) * 6;
          Row3 = (rect.bottom / 16) * 11;

          hBrush = CreateSolidBrush((COLORREF)RED);
          SelectObject (hDC, hBrush);
          Rectangle (hDC, Col2, Row1, Col2+width, Row1+height);
          DeleteObject (hBrush);
                                             // Draw the Blue rectangle.
          hBrush = CreateSolidBrush((COLORREF)BLUE);
          SelectObject (hDC, hBrush);
          Rectangle (hDC, Col1, Row2, Col1+width, Row2+height);
          DeleteObject (hBrush);
                                             // Draw the Green rectangle.
          hBrush = CreateSolidBrush((COLORREF)GREEN);
          SelectObject (hDC, hBrush);
          Rectangle (hDC, Col2, Row3, Col2+width, Row3+height);
          DeleteObject (hBrush);
                                             // Draw the Gray rectangle.
          hBrush = CreateSolidBrush((COLORREF)GRAY);
          SelectObject (hDC, hBrush);
          Rectangle (hDC, Col3, Row2, Col3+width, Row2+height);
          DeleteObject (hBrush);

          EndPaint (hwnd, &Paint);
          return (0);

        case WM_CREATE :
                                             // Create the semaphore.
          hSemaphore = CreateSemaphore (NULL, 0, 1, NULL);

          if (!hSemaphore)
            {
             wsprintf (Buf, "CreateSemaphore() Error = %d",
                       GetLastError());
             MessageBox(hwnd, Buf, "WM_CREATE", MB_OK);
             return (0);
            }

          pColor1  = malloc(sizeof(DWORD));
          *pColor1 = GREEN;                  // Create the Green thread.
          hThread1 = CreateThread (NULL, 0,
                                   (LPTHREAD_START_ROUTINE)ThreadProc,
				   (LPVOID)pColor1, 0,
                                   (LPDWORD)&ThreadID1);

          pColor2  = malloc(sizeof(DWORD));
          *pColor2 = RED;                    // Create the Red thread.
          hThread2 = CreateThread (NULL, 0,
                                   (LPTHREAD_START_ROUTINE)ThreadProc,
				   (LPVOID)pColor2, 0,
                                   (LPDWORD)&ThreadID2);

          pColor3  = malloc(sizeof(DWORD));
          *pColor3 = BLUE;                   // Create the Blue thread.
          hThread3 = CreateThread (NULL, 0,
                                   (LPTHREAD_START_ROUTINE)ThreadProc,
				   (LPVOID)pColor3, 0,
                                   (LPDWORD)&ThreadID3);

          pColor4  = malloc(sizeof(DWORD));
          *pColor4 = GRAY;                   // Create the Gray thread.
          hThread4 = CreateThread (NULL, 0,
                                   (LPTHREAD_START_ROUTINE)ThreadProc,
				   (LPVOID)pColor4, 0,
                                   (LPDWORD)&ThreadID4);

          ReleaseSemaphore (hSemaphore, 1, NULL);

          return (0);


        case WM_DESTROY :                    // Terminate the threads and
            TerminateThread(hThread1, 0);    // clean up.
            TerminateThread(hThread2, 0);
            TerminateThread(hThread3, 0);
            TerminateThread(hThread4, 0);
            free (pColor1);
            free (pColor2);
            free (pColor3);
            free (pColor4);

            PostQuitMessage (0);
            return (0);

       }
    return DefWindowProc (hwnd, message, wParam, lParam);
}


/*************************************************************************\
*
*  FUNCTION:  ThreadProc (LPVOID)
*
*  PURPOSE:   A thread procedure which requests a semaphore, and then
*             draws it's color to the rectangle in the middle of the
*             window.
*
*  VARIABLES USED:
*
*    - Color: An input parameter, a pointer to a DWORD with a color
*             value in it.
*
*    - rect:  The RECT rectangle of the client window, needed to know where
*             the center rectangle resides.
*
*    - hDC:   Handle to the DC of the window.
*
*    - hBrush:
*             Handle to a brush, used to set the rectangle's color to the
*             threads.
*
*    - width, height, Col, Row:
*             DWORDs use to position the rectangle.
*
*  CALLED BY:
*
*    MainWndProc();
*
\*************************************************************************/
VOID ThreadProc ( LPVOID *Color)
{
  RECT rect;
  HDC  hDC;
  HANDLE hBrush;
  DWORD width, height, Col, Row;

  hBrush = CreateSolidBrush((COLORREF)*Color);

  do
    {
     WaitForSingleObject (hSemaphore, INFINITE);
     GetClientRect( hWnd, &rect);

     width =  rect.right / 4;
     height = rect.bottom / 4;
     Col = (rect.right / 16)  * 6;
     Row = (rect.bottom / 16) * 6;

     hDC = GetDC(hWnd);
     SelectObject( hDC, hBrush);
     Rectangle (hDC, Col, Row, Col + width, Row + height);
     ReleaseDC(hWnd, hDC);
     Sleep (500);
     ReleaseSemaphore (hSemaphore, 1, NULL);

    }while(1);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.