1#import "ObjectTesting.h" 2 3#import "Foundation/NSAutoreleasePool.h" 4#import "Foundation/NSThread.h" 5#import "Foundation/NSTimer.h" 6#import "Foundation/NSRunLoop.h" 7#import "GNUstepBase/GSConfig.h" 8 9const NSTimeInterval kDelay = 0.01; 10 11#if GS_USE_LIBDISPATCH_RUNLOOP && __has_feature(blocks) 12# define DISPATCH_RL_INTEGRATION 1 13# if __has_include(<dispatch.h>) 14# include <dispatch.h> 15# else 16# include <dispatch/dispatch.h> 17# endif 18#endif 19 20/** 21 * This is a simple counter object that gets incremented from a different 22 * thread, but by using dispatch_async() to put the actual increment operation 23 * onto the main queue. 24 */ 25@interface Counter : NSObject 26{ 27 NSUInteger counter; 28} 29- (void)increment; 30- (NSUInteger)counter; 31@end 32 33/** 34 * This is the object running in the other thread. It's purpose is to dispatch 35 * five increments to the main queue and then exit. 36 */ 37@interface Queuer : NSObject 38- (void)worker: (Counter*)counter; 39- (void)run; 40- (void)timeout: (NSTimer*)t; 41@end 42 43@implementation Counter 44- (void)increment 45{ 46 counter++; 47} 48 49- (NSUInteger)counter 50{ 51 return counter; 52} 53@end 54 55@implementation Queuer 56 57- (void)worker: (Counter*)counter 58{ 59 NSUInteger i = 0; 60 NSAutoreleasePool *pool = [NSAutoreleasePool new]; 61 for (i = 0; i < 5; i++) 62 { 63# ifdef DISPATCH_RL_INTEGRATION 64 dispatch_async(dispatch_get_main_queue(), ^ { 65 [counter increment]; 66 }); 67# endif 68 NSDate *d = [NSDate dateWithTimeIntervalSinceNow: kDelay]; 69 while ([d timeIntervalSinceNow] > 0) 70 { 71 [[NSRunLoop currentRunLoop] runUntilDate: d]; 72 } 73 } 74 [pool release]; 75} 76 77 78- (void)timeout: (NSTimer*)t 79{ 80 PASS(NO, "Timeout while trying to run blocks on main thread"); 81} 82 83- (void) run 84{ 85 NSDate *until = [NSDate dateWithTimeIntervalSinceNow: 1.0]; 86 Counter *c = [Counter new]; 87 [NSTimer scheduledTimerWithTimeInterval: 1.0 88 target: self 89 selector: @selector(timeout:) 90 userInfo: nil 91 repeats: YES]; 92 93 [NSThread detachNewThreadSelector: @selector(worker:) 94 toTarget: self 95 withObject: c]; 96 97 while ([until timeIntervalSinceNow] > 0) 98 { 99 NSDate *tick = [NSDate dateWithTimeIntervalSinceNow: kDelay * 2]; 100 [[NSRunLoop currentRunLoop] runUntilDate: tick]; 101 if ([c counter] == 5) 102 { 103 break; 104 } 105 } 106 PASS([c counter] == 5, "Dispatch blocks execute on main queue"); 107} 108 109@end 110 111int main(int argc, char *argv[]) 112{ 113 NSAutoreleasePool *pool = [NSAutoreleasePool new]; 114 START_SET("NSRunLoop libdispatch integration") 115# ifndef DISPATCH_RL_INTEGRATION 116 SKIP("No libdispatch, no blocks support or no runloop integration hooks in libdispatch") 117# else 118 [[[Queuer new] autorelease] run]; 119# endif 120 END_SET("NSRunLoop libdispatch integration") 121 [pool release]; 122 return 0; 123} 124