Annotation of q_a/samples/threads/threads.c, revision 1.1

1.1     ! root        1: /*************************************************************************\
        !             2: *  PROGRAM: Threads.c
        !             3: *
        !             4: *  PURPOSE:
        !             5: *
        !             6: *     To demonstrate suspending, resuming, and setting the priorities
        !             7: *     of threads.
        !             8: *
        !             9: *  FUNCTIONS:
        !            10: *
        !            11: *    WinMain()      - Initializes the window, and process the message loop.
        !            12: *    MainWndProc()  - Process messages, launches server & client threads.
        !            13: *    ThreadProc()   - Draws rectangles to the window, demonstrating the
        !            14: *                     threads performance.
        !            15: *
        !            16: *  COMMENTS:
        !            17: *
        !            18: *    To Use:
        !            19: *      When starting this application, two threads are created.  The
        !            20: *      first draws a green box, the second a red.  Both boxes are moved
        !            21: *      about the screen as their individual threads calculate a new
        !            22: *      position and redraws the box.  The user can Suspend either thread,
        !            23: *      Resume them, or change their priority through the menu selections.
        !            24: *      The colored boxes will respond accordingly.
        !            25: *
        !            26: *      Note through out the sample "red thread" or "green thread" are
        !            27: *      referred to.  This simply indicates the thread which draws either the
        !            28: *      red or green rectangle.
        !            29: *
        !            30: \*************************************************************************/
        !            31: 
        !            32: 
        !            33: #include <windows.h>
        !            34: #include <stdlib.h>
        !            35: #include <time.h>
        !            36: #include "threads.h"
        !            37: 
        !            38: 
        !            39: HANDLE hInst;
        !            40: HANDLE hWnd;
        !            41: 
        !            42: /*************************************************************************\
        !            43: *
        !            44: *  FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
        !            45: *
        !            46: *  PURPOSE: calls initialization function, processes message loop
        !            47: *
        !            48: *  COMMENTS:
        !            49: *
        !            50: \*************************************************************************/
        !            51: int APIENTRY WinMain (HANDLE hInstance,
        !            52:                       HANDLE hPrevInstance,
        !            53:                       LPSTR  lpCmdLine,
        !            54:                       int    nCmdShow)
        !            55: {
        !            56:   MSG  msg;
        !            57:   WNDCLASS wc;
        !            58: 
        !            59:   UNREFERENCED_PARAMETER( lpCmdLine );
        !            60:   UNREFERENCED_PARAMETER( hPrevInstance );
        !            61: 
        !            62:   hInst = hInstance;
        !            63: 
        !            64:   wc.style = NULL;                       // Replaces CS_SIZEREDRAW.
        !            65:   wc.lpfnWndProc = (WNDPROC)MainWndProc; // The client window procedure.
        !            66:   wc.cbClsExtra = 0;                     // No room reserved for extra data.
        !            67:   wc.cbWndExtra = 0;
        !            68:   wc.hInstance = hInstance;
        !            69:   wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        !            70:   wc.hCursor = LoadCursor (NULL, IDC_ARROW);
        !            71:   wc.hbrBackground = GetStockObject (WHITE_BRUSH);
        !            72:   wc.lpszMenuName = "Thread_Menu";
        !            73:   wc.lpszClassName = "ThreadsWClass";
        !            74: 
        !            75:   RegisterClass(&wc);
        !            76: 
        !            77: 
        !            78:   hWnd = CreateWindow ("ThreadsWClass",
        !            79:                        "Threads Sample",
        !            80:                        WS_OVERLAPPEDWINDOW,
        !            81:                        CW_USEDEFAULT,
        !            82:                        CW_USEDEFAULT,
        !            83:                        CW_USEDEFAULT,
        !            84:                        CW_USEDEFAULT,
        !            85:                        NULL,
        !            86:                        NULL,
        !            87:                        hInstance,
        !            88:                        NULL);
        !            89: 
        !            90: 
        !            91:   ShowWindow(hWnd, nCmdShow);
        !            92:   while (GetMessage (&msg, NULL, NULL, NULL))
        !            93:     DispatchMessage (&msg);   // Dispatch message to window.
        !            94: 
        !            95:   return (msg.wParam);           // Returns value from PostQuitMessage.
        !            96: 
        !            97: }
        !            98: 
        !            99: /*************************************************************************\
        !           100: *
        !           101: *  FUNCTION:  MainWndProc (HWND, UINT, UINT, LONG)
        !           102: *
        !           103: *  PURPOSE:   To process the windows messages.  This procedure totally
        !           104: *             controls the priority and suspension/resumption of the
        !           105: *             thread.
        !           106: *
        !           107: *  VARIABLES USED:
        !           108: *
        !           109: *    - hThread1, hThread2:
        !           110: *             Static handles to the two created threads.
        !           111: *
        !           112: *    - ThreadID1 ThreadID2:
        !           113: *             DWORDs used in the CreateThread call.
        !           114: *
        !           115: *    - pColor1, pColor2:
        !           116: *             DWORDs used to allocate some memory to use as a parameter
        !           117: *             to pass color values to the threads.  This memory was
        !           118: *             allocated so that the threads wouldn't have to rely on this
        !           119: *             procedures stack for the values.
        !           120: *
        !           121: *    - Buf[80]:
        !           122: *             Character buffer used to write messages to the user.
        !           123: *
        !           124: *    - RedSuspendCnt, GreenSuspendCnt:
        !           125: *             Static DWORDs used to track the count of suspension put
        !           126: *             on the specific thread.
        !           127: *
        !           128: *  MESSAGES:
        !           129: *
        !           130: *    WM_DESTROY:     - Terminates the threads and post the quit message.
        !           131: *    WM_CREATE:      - Allocates memory to hold some color values, and
        !           132: *                      creates the two threads.
        !           133: *    WM_COMMAND
        !           134: *
        !           135: *      IDM_SUSPEND***:
        !           136: *               Suspends the specified thread, updates the globally kept
        !           137: *               count (number of times the thread has been suspended),
        !           138: *               and then produces a message box telling the user the
        !           139: *               number of suspensions.
        !           140: *
        !           141: *      IDM_RESUME***:
        !           142: *               Resumes the specified thread, updates the gobally kept
        !           143: *               count (number of times the thread has been suspended),
        !           144: *               and then produces a message box telling the user the
        !           145: *               number of suspensions.
        !           146: *
        !           147: *      IDM_G***:
        !           148: *               These 5 messages use SetThreadPriority to set the
        !           149: *               priority of the Green Thread.
        !           150: *
        !           151: *      IDM_R***:
        !           152: *               These 5 messages use SetThreadPriority to set the
        !           153: *               priority of the Red Thread.
        !           154: *
        !           155: *  CALLED BY:
        !           156: *
        !           157: *    WinMain();
        !           158: *
        !           159: *  CALLS TO:
        !           160: *
        !           161: *    ThreadProc();
        !           162: *
        !           163: *  COMMENTS:
        !           164: *
        !           165: *
        !           166: \*************************************************************************/
        !           167: 
        !           168: 
        !           169: LONG APIENTRY MainWndProc (HWND hwnd,
        !           170:                            UINT message,
        !           171:                            UINT wParam,
        !           172:                            LONG lParam)
        !           173: {
        !           174:   static HANDLE hThread1, hThread2;
        !           175:   DWORD  ThreadID1, ThreadID2;
        !           176:   CHAR Buf[80];
        !           177:   static DWORD RedSuspendCnt = 0;
        !           178:   static DWORD GreenSuspendCnt = 0;
        !           179:   static DWORD *pColor1, *pColor2;
        !           180: 
        !           181:   switch (message)
        !           182:       {
        !           183: 
        !           184:         case WM_CREATE :
        !           185: 
        !           186:           pColor1 = malloc(sizeof(DWORD));
        !           187:           *pColor1 = GREEN;
        !           188:           hThread1 = CreateThread (NULL, 0,
        !           189:                                    (LPTHREAD_START_ROUTINE)ThreadProc,
        !           190:                                    (LPVOID)pColor1, NULL,
        !           191:                                    (LPDWORD)&ThreadID1);
        !           192: 
        !           193:           if (!hThread1)
        !           194:             {
        !           195:              wsprintf(Buf, "Error in creating Green thread: %d",
        !           196:                       GetLastError());
        !           197:              MessageBox (hwnd, Buf, "WM_CREATE", MB_OK);
        !           198:             }
        !           199: 
        !           200:           Sleep (500);             // Allow some time/distance between the
        !           201:                                    // thread boxes.
        !           202: 
        !           203:           pColor2 = malloc(sizeof(DWORD));
        !           204:           *pColor2 = RED;
        !           205:           hThread2 = CreateThread (NULL, 0,
        !           206:                                    (LPTHREAD_START_ROUTINE)ThreadProc,
        !           207:                                    (LPVOID)pColor2, NULL,
        !           208:                                    (LPDWORD)&ThreadID2);
        !           209:           if (!hThread2)
        !           210:             {
        !           211:              wsprintf(Buf, "Error in creating Red thread: %d",
        !           212:                       GetLastError());
        !           213:              MessageBox (hwnd, Buf, "WM_CREATE", MB_OK);
        !           214:             }
        !           215: 
        !           216: 
        !           217:           return (0);
        !           218: 
        !           219:         case WM_COMMAND:
        !           220:           switch (LOWORD(wParam))
        !           221:             {
        !           222:             case IDM_SUSPENDGREEN:           // Suspends green thread.
        !           223:               SuspendThread (hThread1);
        !           224:               GreenSuspendCnt++;
        !           225:               wsprintf(Buf, "The suspension count for the green thread is now %d",
        !           226:                        GreenSuspendCnt);
        !           227:               MessageBox(hWnd, Buf, "Suspension Count", MB_OK);
        !           228:               return (0);
        !           229: 
        !           230:             case IDM_SUSPENDRED:             // Suspends red thread.
        !           231:               SuspendThread (hThread2);
        !           232:               RedSuspendCnt++;
        !           233:               wsprintf(Buf, "The suspension count for the red thread is now %d",
        !           234:                        RedSuspendCnt);
        !           235:               MessageBox(hWnd, Buf, "Suspension Count", MB_OK);
        !           236:               return (0);
        !           237: 
        !           238:             case IDM_RESUMEGREEN:            // Resumes green thread.
        !           239:               ResumeThread (hThread1);
        !           240:               if (GreenSuspendCnt > 0)
        !           241:                 GreenSuspendCnt--;
        !           242:               wsprintf(Buf, "The suspension count for the green thread is now %d",
        !           243:                        GreenSuspendCnt);
        !           244:               MessageBox(hWnd, Buf, "Suspension Count", MB_OK);
        !           245:               return (0);
        !           246: 
        !           247:             case IDM_RESUMERED:              // Resumes red thread.
        !           248:               ResumeThread (hThread2);
        !           249:               if (RedSuspendCnt > 0)
        !           250:                 RedSuspendCnt--;
        !           251:               wsprintf(Buf, "The suspension count for the red thread is now %d",
        !           252:                        RedSuspendCnt);
        !           253:               MessageBox(hWnd, Buf, "Suspension Count", MB_OK);
        !           254:               return (0);
        !           255: 
        !           256: 
        !           257:             case IDM_GLOW:                   // Sets green lowest possible.
        !           258:               SetThreadPriority (hThread1, THREAD_PRIORITY_LOWEST);
        !           259:               return (0);
        !           260: 
        !           261:             case IDM_GBNORM:                 // Sets green below normal.
        !           262:               SetThreadPriority (hThread1, THREAD_PRIORITY_BELOW_NORMAL);
        !           263:               return (0);
        !           264: 
        !           265:             case IDM_GNORM:                  // Sets green to normal.
        !           266:               SetThreadPriority (hThread1, THREAD_PRIORITY_NORMAL);
        !           267:               return (0);
        !           268: 
        !           269:             case IDM_GANORM:                 // Sets green above normal.
        !           270:               SetThreadPriority (hThread1, THREAD_PRIORITY_ABOVE_NORMAL);
        !           271:               return (0);
        !           272: 
        !           273:             case IDM_GHIGH:                  // Sets green to highest possible.
        !           274:               SetThreadPriority (hThread1, THREAD_PRIORITY_HIGHEST);
        !           275:               return (0);
        !           276: 
        !           277: 
        !           278:             case IDM_RLOW:                   // Sets red to lowest possible
        !           279:               SetThreadPriority (hThread2, THREAD_PRIORITY_LOWEST);
        !           280:               return (0);
        !           281: 
        !           282:             case IDM_RBNORM:                 // Sets red below normal.
        !           283:               SetThreadPriority (hThread2, THREAD_PRIORITY_BELOW_NORMAL);
        !           284:               return (0);
        !           285: 
        !           286:             case IDM_RNORM:                  // Sets red to normal.
        !           287:               SetThreadPriority (hThread2, THREAD_PRIORITY_NORMAL);
        !           288:               return (0);
        !           289: 
        !           290:             case IDM_RANORM:                 // Sets red above normal.
        !           291:               SetThreadPriority (hThread2, THREAD_PRIORITY_ABOVE_NORMAL);
        !           292:               return (0);
        !           293: 
        !           294:             case IDM_RHIGH:                  // Sets red to highest.
        !           295:               SetThreadPriority (hThread2, THREAD_PRIORITY_HIGHEST);
        !           296:               return (0);
        !           297: 
        !           298:             default:
        !           299:               return (0);
        !           300: 
        !           301: 
        !           302:             }
        !           303: 
        !           304:         case WM_DESTROY :
        !           305:             TerminateThread(hThread1, 0);
        !           306:             TerminateThread(hThread2, 0);
        !           307:             free (pColor1);
        !           308:             free (pColor2);
        !           309:             PostQuitMessage (0);
        !           310:             return (0);
        !           311: 
        !           312:        }
        !           313:     return DefWindowProc (hwnd, message, wParam, lParam);
        !           314: }
        !           315: 
        !           316: /*************************************************************************\
        !           317: *
        !           318: *  FUNCTION:  ThreadProc (LPVOID)
        !           319: *
        !           320: *  PURPOSE:   A thread procedure which calculates position on the window
        !           321: *             and draws a colored rectangle.  The color of the rectangle
        !           322: *             is determined by the input parameter, it's border is
        !           323: *             always black (or whatever the pen color is); and since
        !           324: *             the window does not paint between rectangle draws, the
        !           325: *             rectangle leaves a black path in it's wake.
        !           326: *
        !           327: *  VARIABLES USED:
        !           328: *
        !           329: *    - horizontal, vertical:
        !           330: *             Local int used to indicate the next directional move the
        !           331: *             rectangle will make.
        !           332: *
        !           333: *    - ulx, uly:
        !           334: *             Local DWORD used for the Upper Left X corner and Upper
        !           335: *             Upper Left Y position of the rectangle.
        !           336: *
        !           337: *    - rect:  A RECT structure used to determin the current size of the
        !           338: *             window (in case the user resizes it).
        !           339: *
        !           340: *    - hdc:   HDC of the rectangle.
        !           341: *
        !           342: *    - Time:  A SYSTEMTIME structure.  It's milli-second field is used
        !           343: *             to create an apparent random starting point for the
        !           344: *             rectangles.
        !           345: *
        !           346: *    -hBrush: A handle to a Brush object, used to set the color of the
        !           347: *             rectangle.
        !           348: *
        !           349: *    -width, height:
        !           350: *             Local DWORDs used for the width and height of the rectangles.
        !           351: *
        !           352: *  CALLED BY:
        !           353: *
        !           354: *    MainWndProc();
        !           355: *
        !           356: \*************************************************************************/
        !           357: 
        !           358: 
        !           359: VOID ThreadProc ( LPVOID *Color)
        !           360: {
        !           361:   int  horizontal, vertical;
        !           362:   DWORD ulx, uly;
        !           363:   RECT rect;
        !           364:   HDC  hDC;
        !           365:   SYSTEMTIME Time;
        !           366:   HANDLE hBrush;
        !           367:   DWORD width, height;
        !           368: 
        !           369:   width =  10;
        !           370:   height = 10;
        !           371: 
        !           372:   GetSystemTime (&Time);                     // Get the time.
        !           373: 
        !           374:   do{}while(!GetClientRect(hWnd, &rect));    // Loop, making sure window
        !           375:                                              // exists.
        !           376: 
        !           377:   ulx = (Time.wMilliseconds % rect.right);   // Use MOD to get a random
        !           378:   uly = (Time.wMilliseconds % rect.bottom);  // position.
        !           379: 
        !           380:   if(Time.wMilliseconds % 2 == 0)            // Use MOD to pick random
        !           381:     {                                        // directions.
        !           382:      horizontal = 1;
        !           383:      vertical = 1;
        !           384:     }
        !           385:   else
        !           386:     {
        !           387:      horizontal = 1;
        !           388:      vertical = -1;
        !           389:     }
        !           390:                                              // Set color as per input
        !           391:                                              // parameter.
        !           392:   hBrush = CreateSolidBrush((COLORREF)*Color);
        !           393: 
        !           394:   do
        !           395:     {                                        // do forever ...
        !           396:      GetClientRect( hWnd, &rect);
        !           397: 
        !           398:      if ( (ulx+width) > (DWORD)rect.right)   // ... check for right edge,
        !           399:       {
        !           400:       ulx = rect.right - width;
        !           401:       horizontal = -1;                       //   ... if so change direction;
        !           402:       }
        !           403: 
        !           404:      if ((uly+height) > (DWORD)rect.bottom)  // ... check for bottom edge,
        !           405:       {
        !           406:       uly = rect.bottom - height;            //   ... if so change dir.
        !           407:       vertical = -1;
        !           408:       }
        !           409: 
        !           410:      if (uly <= 1)                           // ... check for right edge,
        !           411:       {
        !           412:       uly = 1;
        !           413:       vertical = 1;
        !           414:       }
        !           415: 
        !           416:      if (ulx <= 1)
        !           417:       {                                      // ... check for top edge;
        !           418:       ulx = 1;
        !           419:       horizontal = 1;
        !           420:       }
        !           421: 
        !           422:      hDC = GetDC(hWnd);                      // ... Get DC,
        !           423:      SelectObject( hDC, hBrush);             // ... Set brush color,
        !           424:                                              // ... Draw rectangle,
        !           425:      Rectangle (hDC, ulx, uly, ulx+width, uly+height);
        !           426:      ReleaseDC(hWnd, hDC);                   // ... Release DC
        !           427:      ulx += horizontal;                      // ... Increment/decrement
        !           428:      uly += vertical;                        // ... position.
        !           429: 
        !           430:     }while(1);
        !           431: }

unix.superglobalmegacorp.com

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