Reputation: 17214
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?
Upvotes: 5
Views: 1468
Reputation: 14224
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
Upvotes: 4
Reputation: 9734
It's design decision for implementing scala Futures, all operations (map, flatMap, etc...) requires implicit ExecutionContext.
If you'd like to have better thread reusability and less context switches between threads I'd suggest you to take a look at scalaz Task, slightly different abstraction for delayed computations: http://timperrett.com/2014/07/20/scalaz-task-the-missing-documentation/
Upvotes: 1