1

自動参照カウントの前に、Objective-c で適切なポインター キャストを実行して、 bool OSAtomicCompareAndSwapPtr(void* oldValue, void* newValue, void* volatile *theValue); を使用できるようにすることができます。マルチスレッド アクセスを処理するときにポインターをアトミックにスワップしようとします。

ARC では、これらのポインター キャストは無効です。ARC for iOS で利用できる同等のアトミック ポインター スワップはありますか? この代替手段がまだ利用可能であれば、より高価なロックを回避したいと考えていました。

4

2 に答える 2

0

免責事項:この回答のコードはテストされていません。

まず最初に、ほとんどのポインターの使用では、比較と交換が実際には必要ないことを述べたいと思います。C ポインターの読み取りと書き込みは、それ自体がアトミックです。詳細については、この SO の回答を参照してください。同じことがARMにも当てはまります。したがって、アトミックなゲッターとセッターを実装する場合は、他のスレッドが完全に初期化されたオブジェクトを参照できるようにするためのメモリ バリアのみが必要です。

NSObject * global;
NSObject * get() { return global; }
void set(NSObject * value) { OSMemoryBarrier(); global = value; }

質問に戻りましょう。なぜなら、オブジェクトの比較と交換が実際に使用されている可能性があるからです。キャストは引き続き可能です。異なる方法で宣言するだけです。

NSString * a = @"A";
NSObject * b = @"B";
OSAtomicCompareAndSwapPtrBarrier(
    (__bridge void *)a,
    (__bridge void *)b,
    (__bridge void * *)&a);

ただし、このコードには問題があります。文字列@"A"は参照を失い、@"B"ARC が知らないうちに 2 回参照されます。したがって@"A"、リークが発生し、スコープを離れるときにプログラムがクラッシュする可能性が@"B"あり1ます。

唯一の選択肢は Core Foundation オブジェクトを使用することだと思います。NSObject が CFType とブリッジされた無料であるという事実を利用できます。これに関する決定的な文書は見つかりませんでしたが、常識と実用的な証拠から導き出されたものです。したがって、たとえば、シングルトンを実装することが可能です:

CFTypeRef instance;
Thingamabob * getInstance() {
  if (!instance) {
    CFTypeRef t = (__bridge_retained CFTypeRef)[Thingamabob new];
    if (!OSAtomicCompareAndSwapPtrBarrier(NULL, t, &instance)) {
      CFRelease(t);
    }
  }
  return (__bridge Thingamabob *)instance;
}
于 2014-07-23T20:29:45.340 に答える
0

1つの条件が満たされている場合、およびゲームをプレイする気があれば、これを簡単に使用できる場合があります。

新しいファイルを作成し、ビルド フェーズで ARC を使用しないとマークし、このスワップを小さな C 関数に入れます。関数の先頭でオブジェクトのretainCountsを取得し、それらが等しい場合(およびそれらが自動解放プールに座っていないと信じる理由がある場合)、ARCがそれぞれに適切な解放を保証するため、それらを交換することができます。

等しくない場合は、保持カウントを変更することでゲームをプレイできます。

于 2012-09-12T12:06:48.547 に答える