0

データを表示する前に、バックグラウンドでいくつかの計算を実行する必要がある OpenGL アプリがあります。

順次、私がやっていることは次のとおりです。

  1. prepareData(バックグラウンド スレッドを呼び出します)
  2. _doLongComputation(バックグラウンド スレッドで、 を呼び出します_transferToGPU)
  3. _transferToGPU(メインスレッド)

synchronized同じオブジェクトでブロックを使用しているためglData、クリティカル セクションに複数のスレッドが同時にアクセスするべきではありませんが、残念ながらそうではなく、その理由がわかりません。

何か案は?

コードの重要な部分は次のとおりです。

@property (atomic, retain) NSData *glData;

...snip snip...

- (void) _doLongComputation {
  @synchronized (glData) {
    // Create a buffer (long operation, done in C++)
    unsigned long size;
    unsigned char* buffer = createBuffer(&size);

    // Create NSData to hold it safely
    self.glData = [NSData dataWithBytesNoCopy:buffer length:size freeWhenDone:YES];
  }

  // Don't wand to deal with locking the OpenGL context,
  // so we do all the OpenGL-related stuff in the main queue
  dispatch_async (dispatch_get_main_queue(), ^{
    [self _transferToGPU];
  });
}

- (void) _transferToGPU {
  @synchronized (glData) {
    ...snip snip...

    // Transfer buffer to GPU
    glBufferData(GL_ARRAY_BUFFER,
                 glData.length,
                 glData.bytes,
                 GL_STATIC_DRAW);

    // We're done, so set the buffer to nil
    self.glData = nil;
  }
}

- (void) prepareData {
  [self performSelectorInBackground:@selector(_doLongComputation)];
}
4

1 に答える 1

2

代わりに自分自身で同期する必要があると思います。

変数を同期すると、概念的には、その変数が指すアドレスを使用して暗黙のミューテックスが作成されます。変数が別のオブジェクトを指している場合、コード内で同じ変数であっても、別のミューテックスになります。これは、ブロックに glData を設定する@synchronized(glData)と、同期の試みの目的が無効になることを意味します。

于 2012-10-17T23:32:54.773 に答える