Annotation of q_a/samples/threads/threads.c, revision 1.1.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.