aboutsummaryrefslogtreecommitdiff
path: root/Foundation
diff options
context:
space:
mode:
authorGravatar thomasvl <thomasvl@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2012-12-09 01:12:24 +0000
committerGravatar thomasvl <thomasvl@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2012-12-09 01:12:24 +0000
commitcf8a0a8624021f497d880d186728860cb930fe6a (patch)
treee1d65ee8602301f1fc9d9ce5ec7ec9fd47c83e4b /Foundation
parentc2b4df9148263365e30784ac68306b3105a6f822 (diff)
CFRunLoopStop does NOT act like "join" and block until the thread is stopped.
Use a lock to wait before returning.
Diffstat (limited to 'Foundation')
-rw-r--r--Foundation/GTMNSThread+Blocks.h1
-rw-r--r--Foundation/GTMNSThread+Blocks.m31
2 files changed, 32 insertions, 0 deletions
diff --git a/Foundation/GTMNSThread+Blocks.h b/Foundation/GTMNSThread+Blocks.h
index 16cf4e7..b5df094 100644
--- a/Foundation/GTMNSThread+Blocks.h
+++ b/Foundation/GTMNSThread+Blocks.h
@@ -47,6 +47,7 @@
@interface GTMSimpleWorkerThread : NSThread {
@private
CFRunLoopRef runLoop_;
+ NSConditionLock *runLock_;
}
// Will stop the thread.
diff --git a/Foundation/GTMNSThread+Blocks.m b/Foundation/GTMNSThread+Blocks.m
index cb5243d..f835a0b 100644
--- a/Foundation/GTMNSThread+Blocks.m
+++ b/Foundation/GTMNSThread+Blocks.m
@@ -58,8 +58,26 @@ typedef int (*pthread_setname_np_Ptr)(const char*);
#if GTM_IPHONE_SDK || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
+enum {
+ GTMSimpleThreadIsStarting = 1,
+ GTMSimpleThreadIsFinished
+};
+
@implementation GTMSimpleWorkerThread
+- (id)init {
+ if ((self = [super init])) {
+ runLock_ =
+ [[NSConditionLock alloc] initWithCondition:GTMSimpleThreadIsStarting];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [runLock_ release];
+ [super dealloc];
+}
+
- (void)setThreadDebuggerName:(NSString *)name {
// [NSThread setName:] doesn't actually set the name in such a way that the
// debugger can see it. So we handle it here instead.
@@ -70,6 +88,10 @@ typedef int (*pthread_setname_np_Ptr)(const char*);
}
- (void)main {
+ _GTMDevAssert([runLock_ condition] == GTMSimpleThreadIsStarting,
+ @"Bad start condition %d", [runLock_ condition]);
+ [runLock_ lockWhenCondition:GTMSimpleThreadIsStarting];
+
[self setThreadDebuggerName:[self name]];
// Add a port to the runloop so that it stays alive. Without a port attached
@@ -82,10 +104,19 @@ typedef int (*pthread_setname_np_Ptr)(const char*);
// runloops making it impossible to stop.
runLoop_ = [loop getCFRunLoop];
CFRunLoopRun();
+ [runLock_ unlockWithCondition:GTMSimpleThreadIsFinished];
}
- (void)stop {
CFRunLoopStop(runLoop_);
+ if (![[NSThread currentThread] isEqual:self]) {
+ // If we are calling stop from a separate thread, we block until the
+ // simple thread actually leaves the runloop so there is no race condition
+ // between the current thread and the simple thread. In effect it's a
+ // join operation.
+ [runLock_ lockWhenCondition:GTMSimpleThreadIsFinished];
+ [runLock_ unlockWithCondition:GTMSimpleThreadIsFinished];
+ }
}
- (void)setName:(NSString *)name {