home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Examples / ThreadedApp-1.0.1 / TestCounter.m < prev    next >
Encoding:
Text File  |  1997-04-02  |  4.2 KB  |  231 lines

  1. static char rcsid[] = "$Id: TestCounter.m,v 1.1 1997/04/02 18:28:43 croehrig Exp $";
  2. /*
  3.  *  Counter:  simple counter object that runs in its own thread.
  4.  */
  5. #import <libc.h>
  6. #import <math.h>
  7. #import <appkit/Button.h>
  8. #import <appkit/Slider.h>
  9. #import "Counter.h"
  10. #import "ThreadedApp.h"
  11. #import "tprintf.h"
  12.  
  13. #define INITIAL_INTERVAL    100    // in milliseconds
  14.  
  15. @interface Counter(CounterPrivate)
  16. - (int)incCount;
  17. - (void)counter:sender;
  18. @end
  19.  
  20. @implementation Counter : Object
  21.  
  22. // number of counters created
  23. static int counters;
  24.  
  25. // global variable shared among all Counter instances
  26. static volatile int *countp;
  27.  
  28. // lock to synchronize access to countp
  29. static CJRConditionLock *inclock;
  30.  
  31. #define STOPPED 0
  32. #define RUNNING 1
  33.  
  34. #define myrandom()    (random()/(double)MAXINT)
  35. + initialize
  36. {
  37.     if( self == [Counter class] ){
  38.     srandom(0);
  39.     counters = 1;
  40.     inclock = [[CJRConditionLock alloc] initWithCondition:0];
  41.     tprintf_init();
  42.     }
  43.     return self;
  44. }
  45.  
  46.  
  47. - init
  48. {
  49.     NXScreen *screen;
  50.     NXRect frame;
  51.  
  52.  
  53.     [super init];
  54.     interval = INITIAL_INTERVAL;
  55.     running = NO;
  56.     mynum = counters++;
  57.  
  58.     lastcount = -1;
  59.     count = 0;
  60.     if( [NXApp loadNibSection:"Counter.nib" owner:self] ){
  61.     // set window title...
  62.     title = (char *) malloc( 20*sizeof(char) );  // should be enough...
  63.     sprintf( title, "Counter %d\n", mynum );
  64.     [window setTitle:title];
  65.  
  66.     // move to random location
  67.     [window getFrame:&frame andScreen:&screen];
  68.     frame.size.width = screen->screenBounds.size.width 
  69.               - frame.size.width;
  70.     frame.size.height = screen->screenBounds.size.height
  71.               - frame.size.height;
  72.     frame.origin = screen->screenBounds.origin;
  73.     frame.origin.x += myrandom()*frame.size.width;
  74.     frame.origin.y += myrandom()*frame.size.height;
  75.     [window moveTo:frame.origin.x:frame.origin.y];
  76.     [window makeKeyAndOrderFront:self];
  77.  
  78.     // set values
  79.     [slider setIntValue:interval];
  80.     [intervalField setIntValue:interval];
  81.     [countField setIntValue:count];
  82.  
  83.     runlock = [[CJRConditionLock alloc] initWithCondition:STOPPED];
  84.     // go!
  85.     [self start:self];
  86.     }
  87.     return self;
  88. }
  89.  
  90. - free
  91. {
  92.     if( running )
  93.     [self stop:self];
  94.     
  95.     [runlock free];
  96.     if(title){
  97.     free(title);
  98.     }
  99.     return [super free];
  100. }
  101.  
  102.  
  103. - windowWillClose:sender
  104. {
  105.     [self stop:self];
  106.     [NXApp delayedFree:self];
  107.  
  108.     return self;
  109. }
  110.  
  111.  
  112. // "private" methods
  113.  
  114. - dispCount:(int)i
  115. {
  116.     if( i != lastcount+1 ){
  117.     tprintf("Counter %d:  lost %d message(s)\n", mynum, i-lastcount-1);
  118.     }
  119.     [countField setIntValue:i];
  120.     lastcount = i;
  121.     return self;
  122. }
  123.  
  124.  
  125. - (int)incCount
  126. // a pretty dumb way to increment a counter, but it sure tests
  127. // the callback and lock mechanism...
  128. {
  129.     [inclock lockWhenCondition:0];
  130.     count++;
  131.     countp = &count;
  132.     [inclock unlockWithCondition:mynum];
  133.  
  134.     return count;
  135. }
  136.  
  137.     
  138. - (void)counter:sender
  139. {
  140.     int i;
  141.  
  142.     [runlock lockWhenCondition:RUNNING];
  143.     i = count;
  144.     while( running ){
  145.     // update countField under main thread
  146.     [NXApp callbackTarget:self perform:@selector(dispCount:) with:(id)i];
  147.  
  148.     // increment the counter...
  149.     [NXApp safeCallbackTarget:self perform:@selector(incCount)];
  150.     [inclock lockWhenCondition:mynum];
  151.     i = *countp;
  152.     [inclock unlockWithCondition:0];
  153.     if( i != count ){
  154.         tprintf("Counter %d: count mismatch! ret=%d; count=%d\n", 
  155.         mynum, i, count );
  156.     }
  157.  
  158.     if( interval > 0 )
  159.         [NXApp sleepCurrentThread:interval];
  160.     }
  161.  
  162.     [runlock unlockWithCondition:STOPPED];
  163. }
  164.  
  165.  
  166. // Actions...
  167.  
  168. - start:sender
  169. {
  170.     if( !running ){
  171.     [runlock lock];
  172.     [NXApp detachNewThreadSelector:@selector(counter:) toTarget:self
  173.         withObject:self];
  174.     running = YES;
  175.     [runlock unlockWithCondition:RUNNING];
  176.     }
  177.     return self;
  178. }
  179.  
  180.  
  181. - stop:sender
  182. {
  183.     if( running ){
  184.     running = NO;
  185.     // wait for thread to finish
  186.     [runlock lockWhenCondition:STOPPED];
  187.     [runlock unlock];
  188.     }
  189.  
  190.     return self;
  191. }
  192.  
  193. - startOrStop:sender
  194. {
  195.     if( [sender state] == 0 ){
  196.     [self start:sender];
  197.     } else {
  198.     [self stop:sender];
  199.     }
  200.     return self;
  201. }
  202.  
  203.  
  204. - reset:sender
  205. {
  206.     count = 0;
  207.     return self;
  208. }
  209.  
  210.  
  211. - setInterval:sender
  212. {
  213.     int i, max;
  214.  
  215.     i = [sender intValue];
  216.     max = (int) [slider maxValue];
  217.     if( i < 0 ){
  218.     i = 0;
  219.     } else if( i > max ){
  220.     i = max;
  221.     }
  222.     [slider setIntValue:i];
  223.     [intervalField setIntValue:i];
  224.  
  225.     interval = i;
  226.  
  227.     return self;
  228. }
  229.  
  230. @end
  231.