This PR extends `Std.Channel` to provide a full sync and async API, as well as unbounded, zero sized and bounded channels. A few notes on the implementation: - the bounded channel is inspired by [Go channels on steroids](https://docs.google.com/document/d/1yIAYmbvL3JxOKOjuCyon7JhW4cSv1wy5hC0ApeGMV9s/pub) though currently doesn't do any of the lock-free optimizations - @mhuisi convinced me that having a non-closable channel may be a good idea as this alleviates the need for error handling which is very annoying when working with `Task`. This does complicate the API a little bit and I'm not quite sure whether this is a choice we want users to give. An alternative to this would be to just write `send!` that panics on sending to a closed channel (receiving from a closed channel is not an error), this is for example the behavior that golang goes with.
29 lines
681 B
Text
29 lines
681 B
Text
import Std.Sync.Channel
|
|
|
|
open IO
|
|
|
|
-- not in the run/ directory because then it would be run with -j0
|
|
|
|
#eval do
|
|
let promise ← Promise.new
|
|
promise.resolve 42
|
|
assert! promise.result?.get = some 42
|
|
|
|
|
|
/- Dropping a promise resolves `result?` to `none`. -/
|
|
#eval do
|
|
let promise : Promise Nat ← Promise.new
|
|
assert! promise.result?.get = none
|
|
|
|
#eval show IO _ from do
|
|
let ch ← Std.CloseableChannel.new
|
|
|
|
let out ← IO.mkRef #[]
|
|
ch.sync.send 0
|
|
let drainFinished ← ch.forAsync fun x => out.modify (·.push x)
|
|
ch.sync.send 1
|
|
ch.close
|
|
assert! (← EIO.toBaseIO (ch.sync.send 2)) matches .error .closed
|
|
|
|
IO.wait drainFinished
|
|
assert! (← out.get) = #[0, 1]
|