belozierov / SwiftCoroutine

Swift coroutines for iOS, macOS and Linux.
https://belozierov.github.io/SwiftCoroutine
MIT License
836 stars 51 forks source link

Race Conditions #40

Closed rmehta33 closed 3 years ago

rmehta33 commented 3 years ago

What Happened

Hello,

I created a test program that calculates many points for x^2 on 4 threads. However after running in Xcode 13 with 'Thread Sanitizer' on, it keeps alerting me about a race condition on the first line of 'getFreeQueue()'. This is on an iPhone 12 Pro Simulator running iOS 15.

As this is likely just me not understanding how to use the library, any help would be greatly appreciated!

Demo Code

struct Point {
    var x: Double
    var y: Double
}

class TestingAsyncModel: ObservableObject {
    @Published var text: String = ""

    func getPoints(min: Double, max: Double, numThreads: Int, function: @escaping (Double) -> Double) -> CoFuture<[Point]> {

        func getPoints(min: Double, max: Double) -> CoFuture<[Point]> {
            return DispatchQueue.global().coroutineFuture {
                return stride(from: min, through: max, by: 0.01).map { x in
                    return Point(x: x, y: function(x))
                }
            }
        }

        let spread = (max - min)/Double(numThreads)

        let coroutines = stride(from: min, to: max, by: spread).map { start in
            return getPoints(min: start, max: start + spread)
        }

        return DispatchQueue.global().coroutineFuture {
            return try coroutines.flatMap {try $0.await()}
        }
    }

    init() {
        DispatchQueue.main.startCoroutine { [weak self] in
            self?.text = "start"

            let pointsFuture = self?.getPoints(min: -100, max: 100, numThreads: 4) { x in
                return x * x
            }

            guard let points = try pointsFuture?.await() else {
                return
            }

            self?.text = points.count.description
        }
    }
}

struct TestingAsyncView: View {
    @ObservedObject var model: TestingAsyncModel

    var body: some View {
        Text(model.text)
    }
}