How to undo the future in Scala?

Java Future has a cancel method that can interrupt the thread that runs the Future task. For example, if I complete an intermittent blocking call in Java Future , I can interrupt it later.

Scala Future does not provide a cancel method. Suppose I end an intermittent blocking call in Scala Future . How can I interrupt him?

+46
multithreading scala future
Apr 15 '13 at 7:29
source share
4 answers

This is not yet part of the Future API, but may be added as an extension in the future.

As a workaround, you can use firstCompletedOf to wrap 2 futures - the future you want to cancel and the future that comes from custom Promise . Then you can cancel the future created in this way without fulfilling the promise:

 def cancellable[T](f: Future[T])(customCode: => Unit): (() => Unit, Future[T]) = { val p = Promise[T] val first = Future firstCompletedOf Seq(p.future, f) val cancellation: () => Unit = { () => first onFailure { case e => customCode} p failure new Exception } (cancellation, first) } 

Now you can call this in any future to get a "cancelable wrapper". Usage example:

 val f = callReturningAFuture() val (cancel, f1) = cancellable(f) { cancelTheCallReturningAFuture() } // somewhere else in code if (condition) cancel() else println(Await.result(f1)) 

EDIT:

For a detailed discussion of cancellation, see Chapter 4 in Teaching Parallel Programming in Scala .

+28
Apr 15 '13 at 7:50
source share

I have not tested this, but it has expanded to answer Pablo Francisco Perez Hidalgo. Instead of blocking the java Future wait, we use an intermediate Promise instead.

 import java.util.concurrent.{Callable, FutureTask} import scala.concurrent.{ExecutionContext, Promise} import scala.util.Try class Cancellable[T](executionContext: ExecutionContext, todo: => T) { private val promise = Promise[T]() def future = promise.future private val jf: FutureTask[T] = new FutureTask[T]( new Callable[T] { override def call(): T = todo } ) { override def done() = promise.complete(Try(get())) } def cancel(): Unit = jf.cancel(true) executionContext.execute(jf) } object Cancellable { def apply[T](todo: => T)(implicit executionContext: ExecutionContext): Cancellable[T] = new Cancellable[T](executionContext, todo) } 
+9
Oct 11 '16 at 20:45
source share

By canceling, I think, you would like to forcibly interrupt the future .

Found this code segment: https://gist.github.com/viktorklang/5409467

I did some tests and it seems to be working fine!

Enjoy :)

+7
Oct 23 '13 at 10:40
source share

I think that you can reduce the complexity of the implementations provided with the Java 7 Future interface and its implementations.

Cancellable can build the future of Java, which will be canceled by its cancel method. Another future may await its completion, becoming an observable interface, which in itself is immutable in state:

  class Cancellable[T](executionContext: ExecutionContext, todo: => T) { private val jf: FutureTask[T] = new FutureTask[T]( new Callable[T] { override def call(): T = todo } ) executionContext.execute(jf) implicit val _: ExecutionContext = executionContext val future: Future[T] = Future { jf.get } def cancel(): Unit = jf.cancel(true) } object Cancellable { def apply[T](todo: => T)(implicit executionContext: ExecutionContext): Cancellable[T] = new Cancellable[T](executionContext, todo) } 
+3
Mar 01 '16 at 13:18
source share



All Articles