PageRenderTime 192ms CodeModel.GetById 70ms app.highlight 18ms RepoModel.GetById 72ms app.codeStats 0ms

/thirdparty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m

http://github.com/tomahawk-player/tomahawk
Objective C | 128 lines | 111 code | 17 blank | 0 comment | 9 complexity | a31f60b0b183ca3b6e45a1a1cfa7de3c MD5 | raw file
  1#import "NSObject+SPInvocationGrabbing.h"
  2#import <execinfo.h>
  3
  4#pragma mark Invocation grabbing
  5@interface SPInvocationGrabber ()
  6@property (readwrite, retain, nonatomic) id object;
  7@property (readwrite, retain, nonatomic) NSInvocation *invocation;
  8
  9@end
 10
 11@implementation SPInvocationGrabber
 12- (id)initWithObject:(id)obj;
 13{
 14	return [self initWithObject:obj stacktraceSaving:YES];
 15}
 16
 17-(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack;
 18{
 19	self.object = obj;
 20
 21	if(saveStack)
 22		[self saveBacktrace];
 23
 24	return self;
 25}
 26-(void)dealloc;
 27{
 28	free(frameStrings);
 29	self.object = nil;
 30	self.invocation = nil;
 31	[super dealloc];
 32}
 33@synthesize invocation = _invocation, object = _object;
 34
 35@synthesize backgroundAfterForward, onMainAfterForward, waitUntilDone;
 36- (void)runInBackground;
 37{
 38	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 39	@try {
 40		[self invoke];
 41	}
 42	@finally {
 43		[pool drain];
 44	}
 45}
 46
 47
 48- (void)forwardInvocation:(NSInvocation *)anInvocation {
 49	[anInvocation retainArguments];
 50	anInvocation.target = _object;
 51	self.invocation = anInvocation;
 52	
 53	if(backgroundAfterForward)
 54		[NSThread detachNewThreadSelector:@selector(runInBackground) toTarget:self withObject:nil];
 55	else if(onMainAfterForward)
 56        [self performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:waitUntilDone];
 57}
 58- (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector {
 59	NSMethodSignature *signature = [super methodSignatureForSelector:inSelector];
 60	if (signature == NULL)
 61		signature = [_object methodSignatureForSelector:inSelector];
 62    
 63	return signature;
 64}
 65
 66- (void)invoke;
 67{
 68
 69	@try {
 70		[_invocation invoke];
 71	}
 72	@catch (NSException * e) {
 73		NSLog(@"SPInvocationGrabber's target raised %@:\n\t%@\nInvocation was originally scheduled at:", e.name, e);
 74		[self printBacktrace];
 75		printf("\n");
 76		[e raise];
 77	}
 78
 79	self.invocation = nil;
 80	self.object = nil;
 81}
 82
 83-(void)saveBacktrace;
 84{
 85  void *backtraceFrames[128];
 86  frameCount = backtrace(&backtraceFrames[0], 128);
 87  frameStrings = backtrace_symbols(&backtraceFrames[0], frameCount);
 88}
 89-(void)printBacktrace;
 90{
 91        int x;
 92        for(x = 3; x < frameCount; x++) {
 93		if(frameStrings[x] == NULL) { break; }
 94		printf("%s\n", frameStrings[x]);
 95	}
 96}
 97@end
 98
 99@implementation NSObject (SPInvocationGrabbing)
100-(id)grab;
101{
102	return [[[SPInvocationGrabber alloc] initWithObject:self] autorelease];
103}
104-(id)invokeAfter:(NSTimeInterval)delta;
105{
106	id grabber = [self grab];
107	[NSTimer scheduledTimerWithTimeInterval:delta target:grabber selector:@selector(invoke) userInfo:nil repeats:NO];
108	return grabber;
109}
110- (id)nextRunloop;
111{
112	return [self invokeAfter:0];
113}
114-(id)inBackground;
115{
116    SPInvocationGrabber *grabber = [self grab];
117	grabber.backgroundAfterForward = YES;
118	return grabber;
119}
120-(id)onMainAsync:(BOOL)async;
121{
122    SPInvocationGrabber *grabber = [self grab];
123	grabber.onMainAfterForward = YES;
124    grabber.waitUntilDone = !async;
125	return grabber;
126}
127
128@end