gh123man / Async-Channels

Channels for Swift concurrency
MIT License
103 stars 6 forks source link

AsyncThrowingChannel #13

Closed xlc closed 3 weeks ago

xlc commented 3 weeks ago

It will be great if we can have AsyncThrowingChannel that we can close it with an error, which get thrown on receive. In that way I would be able to communicate if a channel is aborted or not.

Happy to make a PR if needed.

gh123man commented 3 weeks ago

(assuming we are speaking of a buffered channel) this would break receive on close ordering.

Currently when a channel is closed, all buffered elements may be received before nil is returned to signal the channel was closed.

Can you give a more concrete example of your use case? The way I would go about implementing such a behavior would be something like this:


enum StopSignal {
    case error
    case done
}

let data = Channel<String>()
let signal = Channel<StopSignal>()

Task {
    var done = false
    while !done {
        await select {
            receive(data) { print($0!) }
            receive(signal) {
                switch $0! {
                case .error:
                    print("there was an error")
                    done = true
                case .done:
                    print("done processing data")
                    done = true
                }
            }
        }
    }
    print("done!")
}

await data <- "foo"
await data <- "bar"
await signal <- .done

In this example you use two channels: one for data (can be buffered or not) and one for a signal (.done for graceful stop, .error for some kind of error case).

This allows you to interrupt reading the data channel at any time.

xlc commented 3 weeks ago

That will do. It is a bit more complicated than what I suggested but I don't really mind as I can just have wrapper class to handle logic. I still think my approach will have less overheads but that's probably premature optimization.

gh123man commented 3 weeks ago

Sounds good. Thanks for the feedback!