1

I'm currently looking for a Task based alternative for my code using DispatchSemaphore:

func checkForEvents() -> Bool
    let eventSemaphore = DispatchSemaphore(value: 0)
    eventService.onEvent = { _ in
        eventSemaphore.signal()
    }
        
    let result = eventSemaphore.wait(timeout: .now() + 10)
    guard result == .timedOut else {
        return true
    }
    return false
}

I'm trying to detect if any callback events happen in a 10-second time window. This event could happen multiple times, but I only want to know if it occurs once. While the code works fine, I had to convert the enclosing function to async which now shows this warning:

Instance method 'wait' is unavailable from asynchronous contexts; Await a Task handle instead; this is an error in Swift 6`

I'm pretty sure this warning is kind of wrong here since there's no suspension point in this context, but I would still like to know what's the suggested approach in Swift 6 then. I couldn't find anything about this "await a Task handle" so the closest I've got is this:

func checkForEvents() async -> Bool {
    var didEventOccur = false
    eventService.onEvent = { _ in
        didEventOccur = true
    }
    try? await Task.sleep(nanoseconds: 10 * 1_000_000_000)
    return didEventOccur
}

But I can't figure out a way to stop sleeping early if an event occurs...

jacksoor
  • 353
  • 1
  • 12
  • You theoretically could save the `Task` object for this `Task.sleep` and then `cancel` it when the event fires. But, there are probably better alternatives. E.g., if there are a series of `onEvent` calls, that would beg for an `AsyncSequence`. See WWDC 2021 [Meet AsyncSequence](https://developer.apple.com/videos/play/wwdc2021/10058/?time=614). Or if it’s just a single event (i.e., effectively a completion handler callback), then you might use `withCheckedContinuation` to wrap this service in a task. It’s hard to be more specific without broader understanding of this `eventService`. – Rob Oct 24 '22 at 19:39
  • Too many unknowns – lorem ipsum Oct 24 '22 at 21:37
  • @Rob Thanks, I've edited my question. The event can happen multiple times, so a continuation seems problematic. I didn't know that you can do `await task.result`, so cancelling the task in the event handler seems easy enough. I'll also have a look at `AsyncSequence` but it seems to do more than I need. – jacksoor Oct 25 '22 at 08:36
  • IMHO, it sounds precisely like an `AsyncSequence` scenario. I know that the first time you do it, it will feel convoluted and alien, but after a time or two, you‘ll get it and it will suddenly click and make sense... – Rob Oct 25 '22 at 12:16

0 Answers0