Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

concurrent operationがstartするスレッド

タグ: Objective-C NSOperation

isConcurrentではないNSOperationのmainは新しく生成されたスレッドから呼ばれる。
では逆に、isConcurrentなNSOperationのstartはどのスレッドから呼ばれるのか。
ここでは、あまりこのような使い方をすることはないかもしれないが、「isConcurrentではないNSOperation」と「isConcurrentなNSOperation」を混ぜて使い、それらの各種メソッドが呼ばれるスレッドを調べてみる。

#pragma mark base class

@interface OperationBase : NSOperation
{
    NSUInteger number;
}
- (id)initWithNumber:(NSUInteger)n;
- (void)log:(NSString*)string;
@end

@implementation OperationBase
- (id)initWithNumber:(NSUInteger)n
{
    if(self = [super init])
    {
        number = n;
    }
    return self;
}
- (void)log:(NSString*)string
{
    NSLog(@"%@ (%d)%@", [NSThread currentThread], number, string);
}
@end

#pragma mark Concurrent operation class

@interface ConcurrentOperation : OperationBase
{
    BOOL isExecuting;
    BOOL isFinished;
}
@property BOOL isExecuting;
@property BOOL isFinished;
@end

@implementation ConcurrentOperation
@synthesize isExecuting, isFinished;
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key
{
    if([key isEqualToString:@"isExecuting"] || [key isEqualToString:@"isFinished"])
    {
        return YES;
    }
    return [super automaticallyNotifiesObserversForKey:key];
}
- (BOOL)isConcurrent
{
    return YES;
}
- (void)start
{
    [self log:@"Concurrent start"];
    self.isExecuting = YES;
    [NSThread detachNewThreadSelector:@selector(thread) toTarget:self withObject:nil];
}
- (void)thread
{
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    [self log:@"Concurrent thread ->"];
    [NSThread sleepForTimeInterval:0.1];
    self.isExecuting = NO;
    self.isFinished = YES;
    [pool release];
    [self log:@"Concurrent thread <-"];
    [NSThread exit];
}
@end

#pragma mark Non-concurrent operation class

@interface NoncurrentOperation : OperationBase
@end

@implementation NoncurrentOperation
- (void)start
{
    [self log:@"Noncurrent ->"];
    [super start];
    [self log:@"Noncurrent <-"];
}
- (void)main
{
    [self log:@"Noncurrent main"];
    [NSThread sleepForTimeInterval:0.1];
}
@end

#pragma mark -

void run()
{
    NSOperationQueue* queue = [[NSOperationQueue alloc] init];
    [queue setMaxConcurrentOperationCount:1];
    NSLog(@"%@ main", [NSThread currentThread]);
    [queue addOperation:[[[ConcurrentOperation alloc] initWithNumber:1] autorelease]];
    [queue addOperation:[[[NoncurrentOperation alloc] initWithNumber:2] autorelease]];
    [queue addOperation:[[[ConcurrentOperation alloc] initWithNumber:3] autorelease]];
    [queue addOperation:[[[ConcurrentOperation alloc] initWithNumber:4] autorelease]];
    [queue addOperation:[[[NoncurrentOperation alloc] initWithNumber:5] autorelease]];
    [queue addOperation:[[[ConcurrentOperation alloc] initWithNumber:6] autorelease]];
    [queue waitUntilAllOperationsAreFinished];
    [queue release];
}

現在の環境(Mac OS X 10.5.6、XCode 3.1.2)での実行結果は以下の通り。

<NSThread: 0x103b00>{name = (null), num = 1} main
<NSThread: 0x103b00>{name = (null), num = 1} (1)Concurrent start
<NSThread: 0x10e710>{name = (null), num = 2} (1)Concurrent thread ->
<NSThread: 0x10e710>{name = (null), num = 2} (1)Concurrent thread <-
<NSThread: 0x110090>{name = (null), num = 3} (2)Noncurrent ->
<NSThread: 0x110090>{name = (null), num = 3} (2)Noncurrent main
<NSThread: 0x110090>{name = (null), num = 3} (3)Concurrent start
<NSThread: 0x110090>{name = (null), num = 3} (2)Noncurrent <-
<NSThread: 0x10f570>{name = (null), num = 4} (3)Concurrent thread ->
<NSThread: 0x10f570>{name = (null), num = 4} (4)Concurrent start
<NSThread: 0x10f570>{name = (null), num = 4} (3)Concurrent thread <-
<NSThread: 0x10f5b0>{name = (null), num = 5} (4)Concurrent thread ->
<NSThread: 0x10f5b0>{name = (null), num = 5} (4)Concurrent thread <-
<NSThread: 0x10eb70>{name = (null), num = 6} (5)Noncurrent ->
<NSThread: 0x10eb70>{name = (null), num = 6} (5)Noncurrent main
<NSThread: 0x10eb70>{name = (null), num = 6} (6)Concurrent start
<NSThread: 0x10eb70>{name = (null), num = 6} (5)Noncurrent <-
<NSThread: 0x10f000>{name = (null), num = 7} (6)Concurrent thread ->

addOperationした時点で処理を開始できる(同時処理数に空きがある)場合は別として、基本的にはisFinishedをYESに設定した時、そのキー値監視の流れの中で次のNSOperationのstartが呼ばれている。
次のNSOperationがisConcurrentの場合、startはisFinishedをYESにしたスレッドからそのまま呼ばれる。
そうではない場合、startは(detachNewThreadSelectorのように)新しく生成されたスレッドから呼ばれる。

スポンサーサイト

コメント

コメントの投稿

コメントの投稿
管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://idlysphere.blog66.fc2.com/tb.php/192-5c58beb2
この記事にトラックバックする(FC2ブログユーザー)

Appendix

タグ

Blog内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。