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

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);
1.1.1.2 ! root      123:   while (GetMessage (&msg, NULL, 0, 0))
1.1       root      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,
1.1.1.2 ! root      268:                                   (LPVOID)pColor1, 0,
1.1       root      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,
1.1.1.2 ! root      275:                                   (LPVOID)pColor2, 0,
1.1       root      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,
1.1.1.2 ! root      282:                                   (LPVOID)pColor3, 0,
1.1       root      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,
1.1.1.2 ! root      289:                                   (LPVOID)pColor4, 0,
1.1       root      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:      ReleaseDC(hWnd, hDC);
                    368:      Sleep (500);
                    369:      ReleaseSemaphore (hSemaphore, 1, NULL);
                    370: 
                    371:     }while(1);
                    372: }

unix.superglobalmegacorp.com

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