Skip to content

Instantly share code, notes, and snippets.

@mfelsche
Created December 11, 2018 19:53
Show Gist options
  • Save mfelsche/a987e67f6ae804cc256a47736704f459 to your computer and use it in GitHub Desktop.
Save mfelsche/a987e67f6ae804cc256a47736704f459 to your computer and use it in GitHub Desktop.
first function for promises - returning the first fulfilled value
use "promises"
use "collections"
actor _Selector[A: Any #share]
var _completed: Bool = false
var _outstanding: USize
let _promise: Promise[A]
new create(promise: Promise[A], expected: USize) =>
_promise = promise
_outstanding = expected
be fulfill(a: A) =>
if not _completed then
_promise(a)
_completed = true
end
_outstanding = _outstanding - 1
be reject() =>
if (_outstanding == 1) and not _completed then
// no promise was fulfilled
_promise.reject()
end
_outstanding = _outstanding - 1
primitive PromisesExt
fun first[A: Any #share](promises: ReadSeq[Promise[A]]): Promise[A] =>
"""
returns a promise which is fulfilled with the value of the first fulfilled promise from the given promises,
all other fulfilled or rejected promises are ignored.
If all promises got rejected, the returned promise is also rejected.
The returned promise will never be fulfilled if the given ReadSeq promises is empty.
"""
let select_p = Promise[A]
let selector = _Selector[A](select_p, promises.size())
for promise in promises.values() do
promise.next[None](
recover {(a) => selector.fulfill(a) } end,
recover {() => selector.reject() } end)
end
select_p
actor Main
new create(env: Env) =>
let ps = Array[Promise[String]](10)
for x in Range(0, 10) do
ps.push(Promise[String])
end
let p = PromisesExt.first[String](ps)
p.next[None]({(s) => env.out.print(s) })
try
for x in Range(0, 10) do
ps(x)?(x.string())
end
else
env.exitcode(1)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment