Although you already got some answers on how to achieve it with blocking the additional thread to handle the timeout, I would suggest you to try a different way, for the reason Rex Kerr already gave. I don't exactly know, what you are doing in f(), but if it is I/O bound, I would suggest you to just use an asynchronous I/O library instead. If it is some kind of loop, you could pass the timeout value directly into that function and throw a TimeoutException there, if it exceeds the timeout. Example:
import scala.concurrent.duration._
import java.util.concurrent.TimeoutException
def doSth(timeout: Deadline) = {
for {
i <- 0 to 10
} yield {
Thread.sleep(1000)
if (timeout.isOverdue)
throw new TimeoutException("Operation timed out.")
i
}
}
scala> future { doSth(12.seconds.fromNow) }
res3: scala.concurrent.Future[scala.collection.immutable.IndexedSeq[Int]] =
scala.concurrent.impl.Promise$DefaultPromise@3d104456
scala> Await.result(res3, Duration.Inf)
res6: scala.collection.immutable.IndexedSeq[Int] =
Vector(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> future { doSth(2.seconds.fromNow) }
res7: scala.concurrent.Future[scala.collection.immutable.IndexedSeq[Int]] =
scala.concurrent.impl.Promise$DefaultPromise@f7dd680
scala> Await.result(res7, Duration.Inf)
java.util.concurrent.TimeoutException: Operation timed out.
at $anonfun$doSth$1.apply$mcII$sp(<console>:17)
at $anonfun$doSth$1.apply(<console>:13)
at $anonfun$doSth$1.apply(<console>:13)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
...
scala> res7.value
res10: Option[scala.util.Try[scala.collection.immutable.IndexedSeq[Int]]] =
Some(Failure(java.util.concurrent.TimeoutException: Operation timed out.))
This will only use only 1 thread, that will be terminated after timeout + execution time of a single step.
setin a single thread and then split off two futures only after it's set?Future[Unit]will already give you aTryvalue, no need to nest an additionalTry.Future[Try[T]]instead of aFuture[T].Tryat theAwait(I think that really makes a difference there, by capturing the timeout exceptions).