Annotation of q_a/samples/semaphor/sema.c, revision 1.1

1.1     ! root        1: /*************************************************************************\
        !             2: *  PROGRAM: Sema.c
        !             3: *
        !             4: *  PURPOSE:
        !             5: *
        !             6: *     To demonstrate controlling multiple threads through the use of a
        !             7: *     semaphore.
        !             8: *
        !             9: *  FUNCTIONS:
        !            10: *
        !            11: *    WinMain()      - Initializes the window, and process the message loop.
        !            12: *    MainWndProc()  - Process messages, creates semaphore and threads.
        !            13: *
        !            14: *  GLOBAL VARIABLES:
        !            15: *
        !            16: *    - hWnd:  Handle to the window.
        !            17: *    - hSemaphore:
        !            18: *             Handle of the semaphore used between the threads.
        !            19: *
        !            20: *  COMMENTS:
        !            21: *
        !            22: *    To Use:
        !            23: *      Start the application.  You will see five rectangles: a dynamic
        !            24: *      rectangle in the center (always changing color), and four static
        !            25: *      rectangles surrounding it.  Each of the four rectagles has their
        !            26: *      own color: red, blue, green, and gray.  The one in the center
        !            27: *      alternates between these colors.
        !            28: *
        !            29: *      The four static rectangles represent four threads.  These four
        !            30: *      threads compete for the rectangle in the middle, and their access
        !            31: *      is controlled by the semaphore.  When the thread gains control of
        !            32: *      the semaphore, it gets to draw it's color in the center rectangle.
        !            33: *      (note: the threads do not actually draw any of the four static
        !            34: *      rectangles.  To make the code simpler this is handled in the
        !            35: *      WM_PAINT message in the MainWndProc().  They are only meant as
        !            36: *      a visual representation of the threads.  The threads do however
        !            37: *      draw the rectangle in the center with their specific color.)
        !            38: *
        !            39: *    What Happens:
        !            40: *      The semaphore has a use count.  When it is set to zero, any thread
        !            41: *      can access the semaphore and execute the code within its "semaphore
        !            42: *      gate" by using WaitForSingleObject().  When the thread gains
        !            43: *      control of the semaphore usint this call, the use count is
        !            44: *      incremented by one.  When the thread is done executing its code,
        !            45: *      it can call ReleaseSemaphore().  This will decrement the count
        !            46: *      by what ever value you indicate (this code uses 1) signalling
        !            47: *      to any other thread that it may gain control of the semaphore.
        !            48: *
        !            49: *      Note that any thread which has access to the semaphore may decrement
        !            50: *      its use count with ReleaseSemaphore(); the thread does not have
        !            51: *      to have control of the semaphore at the time.
        !            52: *
        !            53: *      In this code, the WM_CREATE message in MainWndProc creates a
        !            54: *      semaphore.  The four threads are then created, each waiting
        !            55: *      on the semaphore .
        !            56: *
        !            57: *      Each of the threads loop, blocking on a WaitForSingleObject()
        !            58: *      call.  Once any thread has set the use count to 0, the thread
        !            59: *      gets to draw draw the center rectagle with its color, and then
        !            60: *      sleeps for half a second before freeing the semaphore again.
        !            61: *      The thread then runs through the loop again.
        !            62: *
        !            63: \*************************************************************************/
        !            64: #include <windows.h>
        !            65: #include <stdlib.h>
        !            66: #include "sema.h"
        !            67: 
        !            68: 
        !            69: HANDLE hInst;
        !            70: HANDLE hWnd;
        !            71: HANDLE hSemaphore;
        !            72: 
        !            73: /*************************************************************************\
        !            74: *
        !            75: *  FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
        !            76: *
        !            77: *  PURPOSE: calls initialization function, processes message loop
        !            78: *
        !            79: *  COMMENTS:
        !            80: *
        !            81: \*************************************************************************/
        !            82: int APIENTRY WinMain (HANDLE hInstance,
        !            83:                       HANDLE hPrevInstance,
        !            84:                       LPSTR  lpCmdLine,
        !            85:                       int    nCmdShow)
        !            86: {
        !            87:   MSG  msg;
        !            88:   WNDCLASS wc;
        !            89: 
        !            90:   UNREFERENCED_PARAMETER( lpCmdLine );
        !            91:   UNREFERENCED_PARAMETER( hPrevInstance );
        !            92: 
        !            93:   hInst = hInstance;
        !            94: 
        !            95:   wc.style = CS_VREDRAW | CS_HREDRAW;
        !            96:   wc.lpfnWndProc = (WNDPROC)MainWndProc;
        !            97:   wc.cbClsExtra = 0;
        !            98:   wc.cbWndExtra = 0;
        !            99:   wc.hInstance = hInstance;
        !           100:   wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        !           101:   wc.hCursor = LoadCursor (NULL, IDC_ARROW);
        !           102:   wc.hbrBackground = GetStockObject (WHITE_BRUSH);
        !           103:   wc.lpszMenuName = "";
        !           104:   wc.lpszClassName = "SemaWClass";
        !           105: 
        !           106:   RegisterClass(&wc);
        !           107: 
        !           108: 
        !           109:   hWnd = CreateWindow ("SemaWClass",
        !           110:                        "Semaphore Sample",
        !           111:                        WS_OVERLAPPEDWINDOW,
        !           112:                        CW_USEDEFAULT,
        !           113:                        CW_USEDEFAULT,
        !           114:                        CW_USEDEFAULT,
        !           115:                        CW_USEDEFAULT,
        !           116:                        NULL,
        !           117:                        NULL,
        !           118:                        hInstance,
        !           119:                        NULL);
        !           120: 
        !           121: 
        !           122:   ShowWindow(hWnd, nCmdShow);
        !           123:   while (GetMessage (&msg, NULL, NULL, NULL))
        !           124:     DispatchMessage (&msg);   // Dispatch message to window.
        !           125: 
        !           126:   return (msg.wParam);           // Returns value from PostQuitMessage.
        !           127: 
        !           128: }
        !           129: 
        !           130: /*************************************************************************\
        !           131: *
        !           132: *  FUNCTION:  MainWndProc (HWND, UINT, UINT, LONG)
        !           133: *
        !           134: *  PURPOSE:   To process the windows messages.  This procedure creates
        !           135: *             the semaphore and the four threads.  It also draws the
        !           136: *             four static rectangles.
        !           137: *
        !           138: *  VARIABLES USED:
        !           139: *
        !           140: *    - hThread?:
        !           141: *             These four static varaibles are handles to the four
        !           142: *             created threads.
        !           143: *
        !           144: *    - ThreadID?:
        !           145: *             These four variables are local DWORDS used in the
        !           146: *             CreateThread() call.
        !           147: *
        !           148: *    - pColor?:
        !           149: *             These four variables are used as pointers to memory
        !           150: *             which is allocated and filled with color values to
        !           151: *             pass as a parameter to each of the threads (so the
        !           152: *             threads know what color they are to paint the rectangle).
        !           153: *
        !           154: *    - Paint: A paint structure used in BeginPaint() and EndPaint().
        !           155: *
        !           156: *    - rect:  A RECT structure used to get the windows client area.
        !           157: *             It's needed to figure out the new relative positions
        !           158: *             of the four static rectangles when the user resizes
        !           159: *             the window.
        !           160: *
        !           161: *    - Col?, Row?, width, height:
        !           162: *             These local DWORDs are used to position the four static
        !           163: *             rectangles and to determin their size.
        !           164: *
        !           165: *    - hDC:   Handle to the DC for the window.
        !           166: *
        !           167: *    - hBrush:
        !           168: *             Handle to a brush, used to set the color of the four static
        !           169: *             rectangles.
        !           170: *
        !           171: *  MESSAGES:
        !           172: *
        !           173: *    WM_CREATE:      - Creates a semaphore; allocates some
        !           174: *                      memory and sets it with color values to be passed
        !           175: *                      as parameter values to the threads.  It then
        !           176: *                      creates four threads, giving each its own color.
        !           177: *
        !           178: *    WM_PAINT:       - Checks the size of the client space and then
        !           179: *                      draws the four static rectangles to their relative
        !           180: *                      positions.
        !           181: *
        !           182: *    WM_DESTROY:     - Terminates the threads, and posts a quit message.
        !           183: *
        !           184: *  CALLED BY:
        !           185: *
        !           186: *    WinMain();
        !           187: *
        !           188: *  CALLS TO:
        !           189: *
        !           190: *    ThreadProc();
        !           191: *
        !           192: \*************************************************************************/
        !           193: 
        !           194: 
        !           195: LONG APIENTRY MainWndProc (HWND hwnd,
        !           196:                            UINT message,
        !           197:                            UINT wParam,
        !           198:                            LONG lParam)
        !           199: {
        !           200:   DWORD  ThreadID1, ThreadID2, ThreadID3, ThreadID4;
        !           201:   RECT   rect;
        !           202:   DWORD  Col1, Col2, Col3, Row1, Row2, Row3, width, height;
        !           203:   HDC    hDC;
        !           204:   HANDLE hBrush;
        !           205:   PAINTSTRUCT Paint;
        !           206:   static HANDLE hThread1, hThread2, hThread3, hThread4;
        !           207:   static DWORD  *pColor1,  *pColor2,  *pColor3,  *pColor4;
        !           208:   CHAR Buf[80];
        !           209: 
        !           210: 
        !           211:   switch (message)
        !           212:       {
        !           213: 
        !           214:         case WM_PAINT:
        !           215:           hDC = BeginPaint (hwnd, &Paint);
        !           216:           GetClientRect( hWnd, &rect);       // Get window rectangle.
        !           217: 
        !           218:           width =  rect.right / 4;           // Calculate static rectangle's
        !           219:           height = rect.bottom / 4;          // width and height.
        !           220: 
        !           221:           Col1 = (rect.right / 16)  * 1;     // Calculate x positions.
        !           222:           Col2 = (rect.right / 16)  * 6;
        !           223:           Col3 = (rect.right / 16)  * 11;
        !           224:                                              // Calculate y positions.
        !           225:           Row1 = (rect.bottom / 16) * 1;
        !           226:           Row2 = (rect.bottom / 16) * 6;
        !           227:           Row3 = (rect.bottom / 16) * 11;
        !           228: 
        !           229:           hBrush = CreateSolidBrush((COLORREF)RED);
        !           230:           SelectObject (hDC, hBrush);
        !           231:           Rectangle (hDC, Col2, Row1, Col2+width, Row1+height);
        !           232:           DeleteObject (hBrush);
        !           233:                                              // Draw the Blue rectangle.
        !           234:           hBrush = CreateSolidBrush((COLORREF)BLUE);
        !           235:           SelectObject (hDC, hBrush);
        !           236:           Rectangle (hDC, Col1, Row2, Col1+width, Row2+height);
        !           237:           DeleteObject (hBrush);
        !           238:                                              // Draw the Green rectangle.
        !           239:           hBrush = CreateSolidBrush((COLORREF)GREEN);
        !           240:           SelectObject (hDC, hBrush);
        !           241:           Rectangle (hDC, Col2, Row3, Col2+width, Row3+height);
        !           242:           DeleteObject (hBrush);
        !           243:                                              // Draw the Gray rectangle.
        !           244:           hBrush = CreateSolidBrush((COLORREF)GRAY);
        !           245:           SelectObject (hDC, hBrush);
        !           246:           Rectangle (hDC, Col3, Row2, Col3+width, Row2+height);
        !           247:           DeleteObject (hBrush);
        !           248: 
        !           249:           EndPaint (hwnd, &Paint);
        !           250:           return (0);
        !           251: 
        !           252:         case WM_CREATE :
        !           253:                                              // Create the semaphore.
        !           254:           hSemaphore = CreateSemaphore (NULL, 0, 1, NULL);
        !           255: 
        !           256:           if (!hSemaphore)
        !           257:             {
        !           258:              wsprintf (Buf, "CreateSemaphore() Error = %d",
        !           259:                        GetLastError());
        !           260:              MessageBox(hwnd, Buf, "WM_CREATE", MB_OK);
        !           261:              return (0);
        !           262:             }
        !           263: 
        !           264:           pColor1  = malloc(sizeof(DWORD));
        !           265:           *pColor1 = GREEN;                  // Create the Green thread.
        !           266:           hThread1 = CreateThread (NULL, 0,
        !           267:                                    (LPTHREAD_START_ROUTINE)ThreadProc,
        !           268:                                    (LPVOID)pColor1, NULL,
        !           269:                                    (LPDWORD)&ThreadID1);
        !           270: 
        !           271:           pColor2  = malloc(sizeof(DWORD));
        !           272:           *pColor2 = RED;                    // Create the Red thread.
        !           273:           hThread2 = CreateThread (NULL, 0,
        !           274:                                    (LPTHREAD_START_ROUTINE)ThreadProc,
        !           275:                                    (LPVOID)pColor2, NULL,
        !           276:                                    (LPDWORD)&ThreadID2);
        !           277: 
        !           278:           pColor3  = malloc(sizeof(DWORD));
        !           279:           *pColor3 = BLUE;                   // Create the Blue thread.
        !           280:           hThread3 = CreateThread (NULL, 0,
        !           281:                                    (LPTHREAD_START_ROUTINE)ThreadProc,
        !           282:                                    (LPVOID)pColor3, NULL,
        !           283:                                    (LPDWORD)&ThreadID3);
        !           284: 
        !           285:           pColor4  = malloc(sizeof(DWORD));
        !           286:           *pColor4 = GRAY;                   // Create the Gray thread.
        !           287:           hThread4 = CreateThread (NULL, 0,
        !           288:                                    (LPTHREAD_START_ROUTINE)ThreadProc,
        !           289:                                    (LPVOID)pColor4, NULL,
        !           290:                                    (LPDWORD)&ThreadID4);
        !           291: 
        !           292:           ReleaseSemaphore (hSemaphore, 1, NULL);
        !           293: 
        !           294:           return (0);
        !           295: 
        !           296: 
        !           297:         case WM_DESTROY :                    // Terminate the threads and
        !           298:             TerminateThread(hThread1, 0);    // clean up.
        !           299:             TerminateThread(hThread2, 0);
        !           300:             TerminateThread(hThread3, 0);
        !           301:             TerminateThread(hThread4, 0);
        !           302:             free (pColor1);
        !           303:             free (pColor2);
        !           304:             free (pColor3);
        !           305:             free (pColor4);
        !           306: 
        !           307:             PostQuitMessage (0);
        !           308:             return (0);
        !           309: 
        !           310:        }
        !           311:     return DefWindowProc (hwnd, message, wParam, lParam);
        !           312: }
        !           313: 
        !           314: 
        !           315: /*************************************************************************\
        !           316: *
        !           317: *  FUNCTION:  ThreadProc (LPVOID)
        !           318: *
        !           319: *  PURPOSE:   A thread procedure which requests a semaphore, and then
        !           320: *             draws it's color to the rectangle in the middle of the
        !           321: *             window.
        !           322: *
        !           323: *  VARIABLES USED:
        !           324: *
        !           325: *    - Color: An input parameter, a pointer to a DWORD with a color
        !           326: *             value in it.
        !           327: *
        !           328: *    - rect:  The RECT rectangle of the client window, needed to know where
        !           329: *             the center rectangle resides.
        !           330: *
        !           331: *    - hDC:   Handle to the DC of the window.
        !           332: *
        !           333: *    - hBrush:
        !           334: *             Handle to a brush, used to set the rectangle's color to the
        !           335: *             threads.
        !           336: *
        !           337: *    - width, height, Col, Row:
        !           338: *             DWORDs use to position the rectangle.
        !           339: *
        !           340: *  CALLED BY:
        !           341: *
        !           342: *    MainWndProc();
        !           343: *
        !           344: \*************************************************************************/
        !           345: VOID ThreadProc ( LPVOID *Color)
        !           346: {
        !           347:   RECT rect;
        !           348:   HDC  hDC;
        !           349:   HANDLE hBrush;
        !           350:   DWORD width, height, Col, Row;
        !           351: 
        !           352:   hBrush = CreateSolidBrush((COLORREF)*Color);
        !           353: 
        !           354:   do
        !           355:     {
        !           356:      WaitForSingleObject (hSemaphore, INFINITE);
        !           357:      GetClientRect( hWnd, &rect);
        !           358: 
        !           359:      width =  rect.right / 4;
        !           360:      height = rect.bottom / 4;
        !           361:      Col = (rect.right / 16)  * 6;
        !           362:      Row = (rect.bottom / 16) * 6;
        !           363: 
        !           364:      hDC = GetDC(hWnd);
        !           365:      SelectObject( hDC, hBrush);
        !           366:      Rectangle (hDC, Col, Row, Col + width, Row + height);
        !           367:      DeleteObject (hBrush);
        !           368:      ReleaseDC(hWnd, hDC);
        !           369:      Sleep (500);
        !           370:      ReleaseSemaphore (hSemaphore, 1, NULL);
        !           371: 
        !           372:     }while(1);
        !           373: }

unix.superglobalmegacorp.com

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