aboutsummaryrefslogtreecommitdiff
path: root/Foundation
diff options
context:
space:
mode:
authorGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2012-03-21 20:00:20 +0000
committerGravatar gtm.daemon <gtm.daemon@7dc7ac4e-7543-0410-b95c-c1676fc8e2a3>2012-03-21 20:00:20 +0000
commit5a2410fb29ea63046f5147b871ad9cd957765b60 (patch)
treea3411d875d728944bcfbc6e9b7af27416f97cb4b /Foundation
parent810aaaee42922022cf9e2ce94de71b14bf558f65 (diff)
[Author: dmaclach]
Add a blocks API to NSThread. R=thomasvl,grobbins DELTA=238 (236 added, 1 deleted, 1 changed)
Diffstat (limited to 'Foundation')
-rw-r--r--Foundation/GTMNSThread+Blocks.h38
-rw-r--r--Foundation/GTMNSThread+Blocks.m51
-rw-r--r--Foundation/GTMNSThread+BlocksTest.m112
3 files changed, 201 insertions, 0 deletions
diff --git a/Foundation/GTMNSThread+Blocks.h b/Foundation/GTMNSThread+Blocks.h
new file mode 100644
index 0000000..4c649c2
--- /dev/null
+++ b/Foundation/GTMNSThread+Blocks.h
@@ -0,0 +1,38 @@
+//
+// GTMNSThread+Blocks.h
+//
+// Copyright 2012 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+//
+// Based on http://www.informit.com/blogs/blog.aspx?uk=Ask-Big-Nerd-Ranch-Blocks-in-Objective-C
+
+#import <Foundation/Foundation.h>
+
+// Extension to NSThread to work with blocks.
+
+#if NS_BLOCKS_AVAILABLE
+
+@interface NSThread (GTMBlocksAdditions)
+
+// If self is not the current thread, the block will be called asynchronously
+// and this method returns immediately.
+// If self is the current thread, the block will be performed immediately, and
+// then this method will return.
+- (void)gtm_performBlock:(void (^)())block;
+
+- (void)gtm_performWaitingUntilDone:(BOOL)wait block:(void (^)())block;
++ (void)gtm_performBlockInBackground:(void (^)())block;
+@end
+
+#endif // NS_BLOCKS_AVAILABLE
diff --git a/Foundation/GTMNSThread+Blocks.m b/Foundation/GTMNSThread+Blocks.m
new file mode 100644
index 0000000..a752ea7
--- /dev/null
+++ b/Foundation/GTMNSThread+Blocks.m
@@ -0,0 +1,51 @@
+//
+// GTMNSThread+Blocks.m
+//
+// Copyright 2012 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+
+#import "GTMNSThread+Blocks.h"
+
+#if NS_BLOCKS_AVAILABLE
+
+@implementation NSThread (GTMBlocksAdditions)
+
++ (void)gtm_runBlockOnCurrentThread:(void (^)())block {
+ block();
+}
+
+- (void)gtm_performBlock:(void (^)())block {
+ if ([[NSThread currentThread] isEqual:self]) {
+ block();
+ } else {
+ [self gtm_performWaitingUntilDone:NO block:block];
+ }
+}
+
+- (void)gtm_performWaitingUntilDone:(BOOL)wait block:(void (^)())block {
+ [NSThread performSelector:@selector(gtm_runBlockOnCurrentThread:)
+ onThread:self
+ withObject:[[block copy] autorelease]
+ waitUntilDone:wait];
+}
+
++ (void)gtm_performBlockInBackground:(void (^)())block {
+ [NSThread performSelectorInBackground:@selector(gtm_runBlockOnCurrentThread:)
+ withObject:[[block copy] autorelease]];
+}
+
+@end
+
+#endif // NS_BLOCKS_AVAILABLE
diff --git a/Foundation/GTMNSThread+BlocksTest.m b/Foundation/GTMNSThread+BlocksTest.m
new file mode 100644
index 0000000..48fb715
--- /dev/null
+++ b/Foundation/GTMNSThread+BlocksTest.m
@@ -0,0 +1,112 @@
+//
+// GTMNSThread+Blocks.h
+//
+// Copyright 2012 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+//
+
+#import "GTMSenTestCase.h"
+#import "GTMNSThread+Blocks.h"
+
+#import "GTMFoundationUnitTestingUtilities.h"
+
+@interface GTMNSThread_BlocksTest : GTMTestCase {
+ @private
+ NSThread *workerThread_;
+ BOOL workerRunning_;
+}
+
+@property (nonatomic, readwrite, getter=isWorkerRunning) BOOL workerRunning;
+@end
+
+@implementation GTMNSThread_BlocksTest
+
+@synthesize workerRunning = workerRunning_;
+
+- (void)stopTestRunning:(GTMUnitTestingBooleanRunLoopContext *)context{
+ [context setShouldStop:YES];
+}
+
+- (void)workerMain:(id)object {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ while ([self isWorkerRunning]) {
+ [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
+ beforeDate:[NSDate distantFuture]];
+ }
+ [pool drain];
+}
+
+- (void)killWorkerThread:(GTMUnitTestingBooleanRunLoopContext *)context {
+ [self setWorkerRunning:NO];
+ [context setShouldStop:YES];
+}
+
+- (void)setUp {
+ [self setWorkerRunning:YES];
+ workerThread_ = [[NSThread alloc] initWithTarget:self
+ selector:@selector(workerMain:)
+ object:nil];
+ [workerThread_ start];
+}
+
+- (void)tearDown {
+ GTMUnitTestingBooleanRunLoopContext *context
+ = [GTMUnitTestingBooleanRunLoopContext context];
+ [self performSelector:@selector(killWorkerThread:)
+ onThread:workerThread_
+ withObject:context
+ waitUntilDone:NO];
+ NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+ STAssertTrue([runLoop gtm_runUpToSixtySecondsWithContext:context], nil);
+ [workerThread_ release];
+}
+
+- (void)testPerformBlock {
+ NSThread *currentThread = [NSThread currentThread];
+ GTMUnitTestingBooleanRunLoopContext *context
+ = [GTMUnitTestingBooleanRunLoopContext context];
+ [workerThread_ gtm_performBlock:^{
+ [self performSelector:@selector(stopTestRunning:)
+ onThread:currentThread
+ withObject:context
+ waitUntilDone:YES];
+ }];
+ NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+ STAssertTrue([runLoop gtm_runUpToSixtySecondsWithContext:context], nil);
+}
+
+- (void)testPerformBlockWaitUntilDone {
+ GTMUnitTestingBooleanRunLoopContext *context
+ = [GTMUnitTestingBooleanRunLoopContext context];
+ [workerThread_ gtm_performWaitingUntilDone:YES block:^{
+ [context setShouldStop:YES];
+ }];
+ STAssertTrue([context shouldStop], nil);
+}
+
+- (void)testPerformBlockInBackground {
+ NSThread *currentThread = [NSThread currentThread];
+ GTMUnitTestingBooleanRunLoopContext *context
+ = [GTMUnitTestingBooleanRunLoopContext context];
+ [NSThread gtm_performBlockInBackground:^{
+ [self performSelector:@selector(stopTestRunning:)
+ onThread:currentThread
+ withObject:context
+ waitUntilDone:YES];
+ }];
+ NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+ STAssertTrue([runLoop gtm_runUpToSixtySecondsWithContext:context], nil);
+}
+
+@end