diff options
-rw-r--r-- | Source/SPThreadAdditions.m | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/Source/SPThreadAdditions.m b/Source/SPThreadAdditions.m index c1f0a52b..74476888 100644 --- a/Source/SPThreadAdditions.m +++ b/Source/SPThreadAdditions.m @@ -29,17 +29,69 @@ // More info at <https://github.com/sequelpro/sequelpro> #import "SPThreadAdditions.h" +#import <objc/objc-runtime.h> + +//this is a "private" class only needed by the +detachNewThreadWithName:… method below. +@interface SPNamedThread : NSObject { + @private + NSString *name; + id object; + SEL selector; +} +- (id)initWithTarget:(id)aObject selector:(SEL)aSelector name:(NSString *)aName; +- (void)run:(id)argument; +@end @implementation NSThread (SPThreadAdditions) + (void)detachNewThreadWithName:(NSString *)aName target:(id)aTarget selector:(SEL)aSelector object:(id)anArgument { - NSThread *newThread = [[NSThread alloc] initWithTarget:aTarget selector:aSelector object:anArgument]; - if (aName) { - [newThread setName:aName]; - } + // -[NSThread setName:] has two limitations when it comes to visibility in Xcode: + // a) Xcode only updates the thread name in UI once (on the first time the thread is shown in the debugger). + // b) Internally this method calls + // int pthread_setname_np(const char*); + // which, as can be seen, does not allow to specify a thread id. Therefore it is skipped if <calling thread != self>. + // Unfortunately this (and not the property of the NSThread) seems to be the actual name shown in Xcode. + // The consequence is, we can only set a thread's name from within the thread, so let's add a proxy object to do that. + SPNamedThread *namedThread = [[SPNamedThread alloc] initWithTarget:aTarget selector:aSelector name:aName]; + + NSThread *newThread = [[NSThread alloc] initWithTarget:namedThread selector:@selector(run:) object:anArgument]; [newThread start]; [newThread autorelease]; + [namedThread autorelease]; +} + +@end + +#pragma mark - + +@implementation SPNamedThread + +- (id)initWithTarget:(id)aObject selector:(SEL)aSelector name:(NSString *)aName +{ + if(self = [super init]) { + name = [aName copy]; + object = [aObject retain]; + selector = aSelector; + } + return self; +} + +- (void)run:(id)argument +{ + [[NSThread currentThread] setName:name]; + + void (*msgsend)(id, SEL, id) = (void (*)(id, SEL, id)) objc_msgSend; //hint for the compiler + + msgsend(object,selector,argument); +} + +- (void)dealloc +{ + [object release], object = nil; + selector = NULL; + [name release], name = nil; + [super dealloc]; } @end |