|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.