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

  1. static char rcsid[] = "$Id: Counter.m,v 1.1 1997/04/02 18:28:27 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    500    // in milliseconds
  14.  
  15. @interface Counter(CounterPrivate)
  16. - (void)counter:sender;
  17. - (int)incCount;
  18. @end
  19.  
  20. @implementation Counter : Object
  21.  
  22. // number of counters created
  23. static int counters;
  24.  
  25. #define STOPPED 0
  26. #define RUNNING 1
  27.  
  28. #define myrandom()    (random()/(double)MAXINT)
  29. + initialize
  30. {
  31.     if( self == [Counter class] ){
  32.     srandom(0);
  33.     counters = 1;
  34.     }
  35.     tprintf_init();
  36.     return self;
  37. }
  38.  
  39.  
  40. - init
  41. {
  42.     NXScreen *screen;
  43.     NXRect frame;
  44.  
  45.  
  46.     [super init];
  47.     interval = INITIAL_INTERVAL;
  48.     running = NO;
  49.     mynum = counters++;
  50.  
  51.     count = 0;
  52.     if( [NXApp loadNibSection:"Counter.nib" owner:self] ){
  53.     // set window title...
  54.     title = (char *) malloc( 20*sizeof(char) );  // should be enough...
  55.     sprintf( title, "Counter %d\n", mynum );
  56.     [window setTitle:title];
  57.  
  58.     // move to random location
  59.     [window getFrame:&frame andScreen:&screen];
  60.     frame.size.width = screen->screenBounds.size.width 
  61.               - frame.size.width;
  62.     frame.size.height = screen->screenBounds.size.height
  63.               - frame.size.height;
  64.     frame.origin = screen->screenBounds.origin;
  65.     frame.origin.x += myrandom()*frame.size.width;
  66.     frame.origin.y += myrandom()*frame.size.height;
  67.     [window moveTo:frame.origin.x:frame.origin.y];
  68.     [window makeKeyAndOrderFront:self];
  69.  
  70.     // set values
  71.     [slider setIntValue:interval];
  72.     [intervalField setIntValue:interval];
  73.     [countField setIntValue:count];
  74.  
  75.     runlock = [[CJRConditionLock alloc] initWithCondition:STOPPED];
  76.     // go!
  77.     [self start:self];
  78.     }
  79.     return self;
  80. }
  81.  
  82. - free
  83. {
  84.     if( running )
  85.     [self stop:self];
  86.     
  87.     [runlock free];
  88.     if(title){
  89.     free(title);
  90.     }
  91.     return [super free];
  92. }
  93.  
  94.  
  95. - windowWillClose:sender
  96. {
  97.     [self stop:self];
  98.     [NXApp delayedFree:self];
  99.  
  100.     return self;
  101. }
  102.  
  103.  
  104. // "private" methods
  105.  
  106. - dispCount:(int)i
  107. {
  108.     [countField setIntValue:i];
  109.     return self;
  110. }
  111.  
  112.  
  113. - (int)incCount
  114. {
  115.     count++;
  116.     return count;
  117. }
  118.  
  119.     
  120. - (void)counter:sender
  121. {
  122.  
  123.     [runlock lockWhenCondition:RUNNING];
  124.     while( running ){
  125.  
  126.     // update countField under main thread
  127.     [NXApp callbackTarget:countField perform:@selector(setIntValue:) 
  128.         with:(id)count];
  129.  
  130.     // use a callback to make absolutely sure a 'reset' isn't lost
  131.     [NXApp callbackAndWaitTarget:self perform:@selector(incCount)];
  132.  
  133.  
  134.     if( interval > 0 )
  135.         [NXApp sleepCurrentThread:interval];
  136.     }
  137.  
  138.     [runlock unlockWithCondition:STOPPED];
  139. }
  140.  
  141.  
  142. // Actions...
  143.  
  144. - start:sender
  145. {
  146.     if( !running ){
  147.     [runlock lock];
  148.     [NXApp detachNewThreadSelector:@selector(counter:) toTarget:self
  149.         withObject:self];
  150.     running = YES;
  151.     [runlock unlockWithCondition:RUNNING];
  152.     }
  153.     return self;
  154. }
  155.  
  156.  
  157. - stop:sender
  158. {
  159.     if( running ){
  160.     running = NO;
  161.     // wait for thread to finish
  162.     [runlock lockWhenCondition:STOPPED];
  163.     [runlock unlock];
  164.     }
  165.  
  166.     return self;
  167. }
  168.  
  169. - startOrStop:sender
  170. {
  171.     if( [sender state] == 0 ){
  172.     [self start:sender];
  173.     } else {
  174.     [self stop:sender];
  175.     }
  176.     return self;
  177. }
  178.  
  179.  
  180. - reset:sender
  181. {
  182.     count = 0;
  183.     return self;
  184. }
  185.  
  186.  
  187. - setInterval:sender
  188. {
  189.     int i, max;
  190.  
  191.     i = [sender intValue];
  192.     max = (int) [slider maxValue];
  193.     if( i < 0 ){
  194.     i = 0;
  195.     } else if( i > max ){
  196.     i = max;
  197.     }
  198.     [slider setIntValue:i];
  199.     [intervalField setIntValue:i];
  200.  
  201.     interval = i;
  202.  
  203.     return self;
  204. }
  205.  
  206. @end
  207.