onmyway133 / blog

🍁 What you don't know is what you haven't learned
https://onmyway133.com/
MIT License
669 stars 33 forks source link

How to deal with actor reentrancy in Swift #912

Open onmyway133 opened 1 year ago

onmyway133 commented 1 year ago

Perform check before and after suspension point

actor Worker {
    var isDoing = false
    var toBeDone = Set<String>()

    func work(string: String) async {
        if isDoing {
            toBeDone.insert(string)
            return
        }

        isDoing = true
        await performHeavyWork(string: string)
        isDoing = false

        if let first = toBeDone.popFirst() {
            await work(string: first)
        }
    }

    private func performHeavyWork(string: String) async {
        try? await Task.sleep(nanoseconds: 5_000_000_000)
        print(string)
    }
}

func main() {
    let worker = Worker()
    Array(0 ... 10).forEach { number in
        Task.detached {
            await worker.work(string: "\(number)")
        }
    }
}

main()

Read more