9

Swift には ObjC のatomicプロパティ属性がないため、Swift クラス用に Swift で「ロック」とそのロックを使用するアトミック プロパティ ラッパーを作成しました。

スレッド サニタイザーを有効にしてテストを実行すると、Atomic プロパティ ラッパーを使用するプロパティでデータ競合が常にキャプチャされます。

機能した唯一のことは、プロパティ ラッパーの宣言を構造体ではなくクラスに変更することでした。ここでの主な問題は、なぜ機能するのかということです。

プロパティ ラッパーに sを追加し、作成されたオブジェクトの数を追跡するために s をprintロックinitしました。構造体/クラスと同じで、別のプロジェクトで問題を再現しようとしましたが、うまくいきませんでした。しかし、問題に似たファイルを追加し、それが機能する理由の推測をお知らせします.

ロック

public class SwiftLock {

    init() { }

   public func sync<R>(execute: () throws -> R) rethrows -> R {
    objc_sync_enter(self)
    defer { objc_sync_exit(self) }
    return try execute()
    }
}

アトミック プロパティ ラッパー

@propertyWrapper struct Atomic<Value> {
    let lock: SwiftLock
    var value: Value

    init(wrappedValue: Value, lock: SwiftLock=SwiftLock()) {
        self.value = wrappedValue
        self.lock = lock
    }

    var wrappedValue: Value {
        get {
            lock.sync { value }
        }
        set {
            lock.sync { value = newValue }
        }
    }
}

モデル (ここのプロパティでデータ競合が発生するはずです)publicVariable2

class Model {
    @Atomic var publicVariable: TimeInterval = 0
    @Atomic var publicVariable2: TimeInterval = 0
    var sessionDuration: TimeInterval {
        min(0, publicVariable - publicVariable2)
    }
}

更新 1: 完全な Xcode プロジェクト: https://drive.google.com/file/d/1IfAsOdHKOqfuOp-pSlP75FLF32iVraru/view?usp=sharing

4

1 に答える 1