Future
Java の に似た Objective-C でクラスを実装してjava.util.concurrent.Future
いますが、単純なニーズにより適しています。実装は次のとおりです。
typedef id (^TaskBlock)();
static int NotDone = 0;
static int Done = 1;
@implementation Future
- (id)initWithBlock:(TaskBlock)aBlock {
if((self = [super init])) {
lock = [[NSConditionLock alloc] initWithCondition:NotDone];
block = aBlock;
}
return self;
}
- (void)set:(id)aValue {
if ([lock tryLockWhenCondition:NotDone]) {
[lock lockWhenCondition:NotDone];
value = aValue;
[lock unlockWithCondition:Done];
}
}
- (id)get {
DLog(@"Retrieving future value");
[lock lockWhenCondition:Done];
id v = value;
[lock unlock];
return v;
}
- (void)start {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
DLog(@"Requesting future value");
[self set:block()];
DLog(@"Future value set");
});
}
@end
私がそれを使用しているとき、1 つのスレッドが最初に次のget:
ようにブロックされます (それは、 で表される長い計算block
が完了するのを待ちます)。
frame #0: 0x9139783e libsystem_kernel.dylib`__psynch_cvwait + 10
frame #1: 0x904a4e78 libsystem_c.dylib`_pthread_cond_wait + 914
frame #2: 0x904a4f7b libsystem_c.dylib`pthread_cond_timedwait_relative_np + 47
frame #3: 0x00b565f2 Foundation`-[NSCondition waitUntilDate:] + 389
frame #4: 0x00b26fc0 Foundation`-[NSConditionLock lockWhenCondition:beforeDate:] + 285
frame #5: 0x00b26e9d Foundation`-[NSConditionLock lockWhenCondition:] + 69
frame #6: 0x0000c335 Jungle`-[Future get](self=0x0757e220, _cmd=0x0000ec3a) + 85 at Future.m:52
frame #7: 0x0000ab23 Jungle`-[GADelayedBinding waitDelayed](self=0x071c39e0, _cmd=0x0000eb1d) + 99 at GADelayedBinding.m:44
frame #8: 0x00007a26 Jungle`-[GATuple waitDelayed](self=0x071baa70, _cmd=0x0000eb1d) + 390 at GATuple.m:99
frame #9: 0x000098fa Jungle`-[GAUnifier unify:with:dynamicContext:](self=0x07561030, _cmd=0x0000eaf8, query=0x071bcc50, base=0x07182f40, dynamicContext=0x00000000) + 2442 at GAUnifier.m:85
frame #10: 0x00009b06 Jungle`-[GAUnifier unify:with:](self=0x07561030, _cmd=0x0000e71e, query=0x071bcc50, base=0x07182f40) + 118 at GAUnifier.m:93
frame #11: 0x00002b44 Jungle`__32-[ViewController viewDidAppear:]_block_invoke(.block_descriptor=0x0756a6a0) + 84 at ViewController.m:38
frame #12: 0x04a0a53f libdispatch.dylib`_dispatch_call_block_and_release + 15
frame #13: 0x04a1c014 libdispatch.dylib`_dispatch_client_callout + 14
frame #14: 0x04a0d2e8 libdispatch.dylib`_dispatch_root_queue_drain + 335
frame #15: 0x04a0cfcb libdispatch.dylib`_dispatch_worker_thread3 + 20
frame #16: 0x904a2b24 libsystem_c.dylib`_pthread_wqthread + 346
計算が終了すると、ここでデッドロックに関するエラーが発生します。
frame #0: 0x00b9f80f Foundation`_NSLockError
frame #1: 0x00b26f6f Foundation`-[NSConditionLock lockWhenCondition:beforeDate:] + 204
frame #2: 0x00b26e9d Foundation`-[NSConditionLock lockWhenCondition:] + 69
frame #3: 0x0000c268 Jungle`-[Future set:](self=0x0757e220, _cmd=0x0000ec35, aValue=0x07578b40) + 136 at Future.m:43
frame #4: 0x0000c501 Jungle`__15-[Future start]_block_invoke(.block_descriptor=0x0757e330) + 113 at Future.m:63
frame #5: 0x04a0a53f libdispatch.dylib`_dispatch_call_block_and_release + 15
frame #6: 0x04a1c014 libdispatch.dylib`_dispatch_client_callout + 14
frame #7: 0x04a0d2e8 libdispatch.dylib`_dispatch_root_queue_drain + 335
frame #8: 0x04a0cfcb libdispatch.dylib`_dispatch_worker_thread3 + 20
frame #9: 0x904a2b24 libsystem_c.dylib`_pthread_wqthread + 346
私は何を間違っていますか?私のロックが待っているすべての条件は、私には正しいように見えます。