home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / System / ThreadLib 1.0d1 / ThreadsTest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-11  |  4.6 KB  |  208 lines  |  [TEXT/KAHL]

  1. /* See the file Distribution for distribution terms.
  2.     (c) Copyright 1994 Ari Halberstadt */
  3.  
  4. /* A quick hack to test my threads library. A dialog is displayed with two
  5.     counters, each incremented in its own thread. The display of the counters
  6.     is updated once a second from a third thread. The "count1" line contains
  7.     the value of the first counter, the "count2" line contains the value of
  8.     the second counter. The "elapsed" line contains the number of ticks between
  9.     updates (should be close to 60 ticks). The "remaining" line shows the number
  10.     of ticks till the program automatically quits (about 30 seconds, or 1800
  11.     ticks). Click the "Quit" button to quit the program, or "Raise Exception"
  12.     to quit the program by raising an exception.
  13.     
  14.     While writing this I discovered that my threads library and THINK C's
  15.     console library don't get along too great (I haven't tracked down exactly
  16.     what's wrong), so I changed it to use a simple dialog.
  17.     
  18.     94/02/10 aih - created */
  19.  
  20. #include <limits.h>
  21. #include "ThreadLib.h"
  22.  
  23. #define rDialog (128)
  24.  
  25. /* dialog items */
  26. enum {
  27.     iQuit = 5,
  28.     iException,
  29.     iCount1,
  30.     iCount2,
  31.     iElapsed,
  32.     iRemaining,
  33.     iLast
  34. };
  35.  
  36. /* the counters */
  37. static long count1;
  38. static long count2;
  39.  
  40. /* the threads */
  41. static ThreadHandle hthreadmain;
  42. static ThreadHandle hthread1;
  43. static ThreadHandle hthread2;
  44. static ThreadHandle hthread3;
  45.  
  46. /* the dialog */
  47. static DialogPtr gDialog;
  48.  
  49. /* initialize application heap */
  50. static void HeapInit(long stack, short masters)
  51. {
  52.     SetApplLimit(GetApplLimit() - stack);
  53.     MaxApplZone();
  54.     while (masters-- > 0)
  55.         MoreMasters();
  56. }
  57.  
  58. /* initialize managers */
  59. static void ManagersInit(void)
  60. {
  61.     EventRecord event;
  62.     short i;
  63.     
  64.     /* standard initializations */
  65.     InitGraf((Ptr) &thePort);
  66.     InitFonts();
  67.     InitWindows();
  68.     InitMenus();
  69.     TEInit();
  70.     InitDialogs(NULL);
  71.     FlushEvents(everyEvent, 0);
  72.     InitCursor();
  73.     
  74.     /* so first window will be frontmost */
  75.     for (i = 0; i < 4; i++)
  76.         EventAvail(everyEvent, &event);
  77. }
  78.  
  79. /* thread to increment the first counter */
  80. static void thread1(void *data)
  81. {
  82.     for (;;) {
  83.         count1++;
  84.         ThreadYield(0); /* runs this thread as often as possible */
  85.     }
  86. }
  87.  
  88. /* thread to increment the second counter */
  89. static void thread2(void *data)
  90. {    
  91.     for (;;) {
  92.         count2++;
  93.         ThreadYield(0); /* runs this thread as often as possible */
  94.     }
  95. }
  96.  
  97. /* thread to update display of counters in dialog */
  98. static void thread3(void *data)
  99. {
  100.     TicksType ticks;
  101.     short type;
  102.     Handle item;
  103.     Rect box;
  104.     Str255 str;
  105.     
  106.     for (;;) {
  107.         if (gDialog) {
  108.             NumToString(count1, str);
  109.             GetDItem(gDialog, iCount1, &type, &item, &box);
  110.             SetIText(item, str);
  111.             NumToString(count2, str);
  112.             GetDItem(gDialog, iCount2, &type, &item, &box);
  113.             SetIText(item, str);
  114.             ticks = TickCount();
  115.             ThreadYield(60); /* runs this thread every seconds */
  116.             if (gDialog) {
  117.                 NumToString(TickCount() - ticks, str);
  118.                 GetDItem(gDialog, iElapsed, &type, &item, &box);
  119.                 SetIText(item, str);
  120.             }
  121.         }
  122.     }
  123. }
  124.  
  125. /* create all of the threads */
  126. static void ThreadsInit(void)
  127. {
  128.     hthreadmain = ThreadBeginMain(NULL, NULL, NULL);
  129.     hthread1 = ThreadBegin(thread1, NULL, NULL, NULL, 0);
  130.     hthread2 = ThreadBegin(thread2, NULL, NULL, NULL, 0);
  131.     hthread3 = ThreadBegin(thread3, NULL, NULL, NULL, 0);
  132. }
  133.  
  134. /* dispose of all of the threads */
  135. static void ThreadsDispose(void)
  136. {
  137.     ThreadEnd(hthread1);
  138.     ThreadEnd(hthread2);
  139.     ThreadEnd(hthread3);
  140.     ThreadEnd(hthreadmain);
  141. }
  142.  
  143. /* filter procedure for the dialog, quits when time has elapsed and allows
  144.     other threads to run by calling ThreadYield */
  145. static pascal Boolean filter(DialogPtr dlg, EventRecord *event,
  146.     short *itemHit)
  147. {
  148.     static TicksType ticks;
  149.     static TicksType stop;
  150.     short type;
  151.     Handle item;
  152.     Rect box;
  153.     Str255 str;
  154.     
  155.     if (! stop)
  156.         stop = TickCount() + 60 * 30; /* run for 30 seconds */
  157.     if (TickCount() >= stop) {
  158.         *itemHit = iQuit;
  159.         return(true);
  160.     }
  161.     if (TickCount() - ticks > 60) {
  162.         NumToString(stop - TickCount(), str);
  163.         GetDItem(dlg, iRemaining, &type, &item, &box);
  164.         SetIText(item, str);
  165.         ticks = TickCount();
  166.     }        
  167.     if (event->what == nullEvent) {
  168.         ThreadYield(60);    /* runs this thread every second, when an event
  169.                                     is pending, or when no other thread is
  170.                                     scheduled */
  171.     }
  172.     return(false);
  173. }
  174.  
  175. /* create the dialog and run the program */
  176. static void Run(void)
  177. {
  178.     short item;
  179.     
  180.     TRY {
  181.         gDialog = GetNewDialog(rDialog, NULL, (WindowPtr) -1);
  182.         do {
  183.             ModalDialog(filter, &item);
  184.             switch (item) {
  185.             case iException:
  186.                 FailOSErr(-1);
  187.                 break;
  188.             }
  189.         } while (item != iQuit);
  190.     } CLEANUP {
  191.         if (gDialog)
  192.             DisposeDialog(gDialog);
  193.         gDialog = NULL;
  194.     } ENDTRY;
  195. }
  196.  
  197. void main(void)
  198. {
  199.     TRY {
  200.         HeapInit(0, 4);
  201.         ManagersInit();
  202.         ThreadsInit();
  203.         Run();
  204.     } CLEANUP {
  205.         ThreadsDispose();
  206.     } ENDTRY;
  207. }
  208.