diff options
Diffstat (limited to 'UICaboodle/UCYield.h')
-rw-r--r-- | UICaboodle/UCYield.h | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/UICaboodle/UCYield.h b/UICaboodle/UCYield.h new file mode 100644 index 0000000..dc75f8f --- /dev/null +++ b/UICaboodle/UCYield.h @@ -0,0 +1,64 @@ +@interface NSObject (UICaboodle) +- (id) yieldToSelector:(SEL)selector withObject:(id)object; +- (id) yieldToSelector:(SEL)selector; +@end + +@implementation NSObject (UICaboodle) + +- (void) doNothing { +} + +- (void) _yieldToContext:(NSMutableArray *)context { _pooled + SEL selector(reinterpret_cast<SEL>([[context objectAtIndex:0] pointerValue])); + id object([[context objectAtIndex:1] nonretainedObjectValue]); + volatile bool &stopped(*reinterpret_cast<bool *>([[context objectAtIndex:2] pointerValue])); + + /* XXX: deal with exceptions */ + id value([self performSelector:selector withObject:object]); + + NSMethodSignature *signature([self methodSignatureForSelector:selector]); + [context removeAllObjects]; + if ([signature methodReturnLength] != 0 && value != nil) + [context addObject:value]; + + stopped = true; + + [self + performSelectorOnMainThread:@selector(doNothing) + withObject:nil + waitUntilDone:NO + ]; +} + +- (id) yieldToSelector:(SEL)selector withObject:(id)object { + /*return [self performSelector:selector withObject:object];*/ + + volatile bool stopped(false); + + NSMutableArray *context([NSMutableArray arrayWithObjects: + [NSValue valueWithPointer:selector], + [NSValue valueWithNonretainedObject:object], + [NSValue valueWithPointer:const_cast<bool *>(&stopped)], + nil]); + + NSThread *thread([[[NSThread alloc] + initWithTarget:self + selector:@selector(_yieldToContext:) + object:context + ] autorelease]); + + [thread start]; + + NSRunLoop *loop([NSRunLoop currentRunLoop]); + NSDate *future([NSDate distantFuture]); + + while (!stopped && [loop runMode:NSDefaultRunLoopMode beforeDate:future]); + + return [context count] == 0 ? nil : [context objectAtIndex:0]; +} + +- (id) yieldToSelector:(SEL)selector { + return [self yieldToSelector:selector withObject:nil]; +} + +@end |