Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Scala's Future.onComplete needs an ExecutionContext

Can't Promise.complete just run Future.onComplete's callback, and not go all the way through a ExecutionContext and, as I understand it, schedule Future.onComplete's callback for later and potentially run it in another thread?

like image 660
Yuri Geinish Avatar asked Jan 20 '15 17:01

Yuri Geinish


1 Answers

You can provide your own ExecutionContext to onComplete, that will run the code on the same thread:

val immediateContext: ExecutionContext = new ExecutionContext {
  def execute(runnable: Runnable) {
    runnable.run()
  }
  def reportFailure(cause: Throwable) {}
}

You can even make it implicit, and for cases where you want the execution to take place in another thread, you can provide scala.concurrent.ExecutionContext.global or some other context.

Here is a test, how it works:

val immediateContext: ExecutionContext = new ExecutionContext {
  override def reportFailure(cause: Throwable): Unit = {}
  override def execute(runnable: Runnable): Unit = {
    println("Executing")
    runnable.run()
    println("Executed")
  }
}

def testContext(): Unit = {
  println("Scheduling on an uncompleted future")
  val p = Promise[Int]()
  println("Scheduling")
  p.future.onComplete { _ => println("Completed") }(immediateContext)
  println("Scheduled")
  p.complete(Success(5))

  println()

  println("Scheduling on an already completed future")
  val p2 = Promise[Int]().complete(Success(5))
  println("Scheduling")
  p2.future.map { n =>
    println("Mapping")
    n * 2
  }(immediateContext).onComplete{
    case Success(n) => println(s"Completed: $n") 
    case _ =>
  }(immediateContext)
  println("Scheduled")

  println()

  println("Using scala.concurrent.ExecutionContext.global for comparison")
  val p3 = Promise[Int]().complete(Success(5))
  println("Scheduling")
  p3.future.onComplete {
    _ => println("Completed")
  }(concurrent.ExecutionContext.global)
  println("Scheduled")
}

Running testContext() will print

Scheduling on an uncompleted future
Scheduling
Scheduled
Executing
Completed
Executed

Scheduling on an already completed future
Scheduling
Executing
Mapping
Executed
Executing
Completed: 10
Executed
Scheduled

Using scala.concurrent.ExecutionContext.global for comparison
Scheduling
Scheduled
Completed
like image 137
Kolmar Avatar answered Oct 27 '22 00:10

Kolmar