Swift How to wait until a specific condition is met

516 views Asked by At

I've looked through just about every question on this topic I could find but I've had little success. I need to run a function on an array of actors conforming to a specific actor protocol. Because these are actors, I need an async call. But I also need to run these functions in a specific order, and I'm not going to describe how I get the order, just suffice it to say that I have it. I am also using the following asyncForEach function, though I'm open to not doing this.

extension Sequence {
    func asyncForEach (
        _ operation: @escaping (Element) async -> Void
    ) async {
        // A task group automatically waits for all of its
        // sub-tasks to complete, while also performing those
        // tasks in parallel:
        await withTaskGroup(of: Void.self) { group in
            for element in self {
                group.addTask {
                    await operation(element)
                }
            }
        }
    }
}

Now I have some protocol

protocol ProtocolConformingActors: Actor {
    func bar() async throws
}

This leads me to running my function

func foo() async throws {
    let actorsAndOrders: [Int: ProtocolConformingActors] = [1:actor1, 2:actor2, 3:actor3]

    // Get order
    var orders: [Int] = []
    for entry in actorsAndOrders {
        orders.append(entry.key)
    }
    orders.sort()

    // Run func
    await orders.asyncForEach { order in
        let actor = actorsAndOrders[order]

        try await actor?.bar()
    }
}

And this is where the problem occurs. Like I mentioned above, these calls need to be async because bar() is modifying isolated properties on each actor. Because in order to make this happen, I need to use the asyncForEach, but as I understand it, the asyncForEach loop sets up and runs each function bar() in parallel. But they need to be run in order.

Is there a way I can make each thread wait until a condition is met?

I was thinking I might be able to use the condition orders[0] == order and when bar() is done running, remove the first entry from the orders array, which could make it tell the next thread it can wake up again.

But while the apple documentation seems to indicate that there is a wait(until:) function on NSCondition, I can't seem to make it work.

0

There are 0 answers