aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPThreadAdditions.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPThreadAdditions.m')
-rw-r--r--Source/SPThreadAdditions.m60
1 files changed, 56 insertions, 4 deletions
diff --git a/Source/SPThreadAdditions.m b/Source/SPThreadAdditions.m
index c1f0a52b..f61b6289 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
+{
+ SPClear(object);
+ selector = NULL;
+ SPClear(name);
+ [super dealloc];
}
@end