in util-core/src/main/scala/com/twitter/util/Future.scala [1206:1266]
def collectToTry[A](fs: JList[Future[A]]): Future[JList[Try[A]]] = Futures.collectToTry(fs)
/**
* "Select" off the first future to be satisfied. Return this as a
* result, with the remainder of the Futures as a sequence.
*
* @param fs the futures to select from. Must not be empty.
*
* @see [[selectIndex]] which can be more performant in some situations.
*/
def select[A](fs: Seq[Future[A]]): Future[(Try[A], Seq[Future[A]])] =
if (fs.isEmpty) {
Future.exception(new IllegalArgumentException("empty future list"))
} else {
val p = Promise.interrupts[(Try[A], Seq[Future[A]])](fs: _*)
val size = fs.size
val as = {
val array = new Array[(Promise[A] with Promise.Detachable, Future[A])](size)
val iterator = fs.iterator
var i = 0
while (iterator.hasNext) {
val f = iterator.next()
array(i) = Promise.attached(f) -> f
i += 1
}
array
}
var i = 0
while (i < size) {
val tuple = as(i)
val a = tuple._1
val f = tuple._2
a.respond { t =>
if (!p.isDefined) {
val filtered = {
val buf = Vector.newBuilder[Future[A]]
buf.sizeHint(size - 1)
var j = 0
while (j < size) {
val (_, fi) = as(j)
if (fi ne f)
buf += fi
j += 1
}
buf.result()
}
p.updateIfEmpty(Return(t -> filtered))
var j = 0
while (j < size) {
as(j)._1.detach()
j += 1
}
}
}
i += 1
}
p
}