2

I saw an example here:

val fut = Future { ... // my body function } // my body function starts here
fut onComplete { ... // my callback }

Looks like I may add the callback after the completion of my body function. Is it still invoked ? Anyway, I would prefer to add callbacks to a future before my function starts running. Does it make sense ? How can I do that ?

Michael
  • 41,026
  • 70
  • 193
  • 341

3 Answers3

7

The doc is pretty clear about your first point:

If the future has already been completed when registering the callback, then the callback may either be executed asynchronously, or sequentially on the same thread.

As for your latter concern -- you can put code you need to run as a first line of future body, for example:

def futureWithBefore[T](body: => T, before: => Any) = future {
  before()
  body()
} 
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
  • I think the OP wanted to make sure the callback registration happens before the future is executed and not to execute code before the future's body – pagoda_5b May 15 '13 at 08:45
1

If you want to control the point of execution of a future, you could chain it with a Promise.

import scala.concurrent._
import ExecutionContext.Implicits.global

val initialPromise = promise[Unit]

// add your computations
val fut = initialPromise.future map { _ => println("My Future") }

// register callbacks
fut onComplete { _ => println("My Callback") }

// run
initialPromise.success()

Using something other than Unit allows you to feed the computation with arbitrary values.

Debilski
  • 66,976
  • 12
  • 110
  • 133
  • This is correct but I don't see any advantage over om-nom-nom's simpler approach. Did I miss something? – Régis Jean-Gilles May 15 '13 at 06:03
  • Composed this way, future and callback could run on different executors. And Promise needs more press coverage. (I totally missed OP's question.) – som-snytt May 15 '13 at 07:15
1

Or something like:

$ skala
Welcome to Scala version 2.11.0-20130423-194141-5ec9dbd6a9 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_06).
Type in expressions to have them evaluated.
Type :help for more information.

scala> :pa
// Entering paste mode (ctrl-D to finish)

import scala.concurrent._
import ExecutionContext.Implicits.global

// Exiting paste mode, now interpreting.

import scala.concurrent._
import ExecutionContext.Implicits.global

scala> val x = Future { Thread sleep 60000L ; 7 }
x: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@44b0c913

scala> def todo = println("Extra work before the job.")
todo: Unit

scala> def something(i: Int) = { todo ; i }
something: (i: Int)Int

scala> x map something
res0: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@2a5457ea

scala> def f(i: Int) = { println(s"Job $i"); i+1 }
f: (i: Int)Int

scala> .map (f)
res1: scala.concurrent.Future[Int] = scala.concurrent.impl.Promise$DefaultPromise@32bc46f4

scala> .value
res2: Option[scala.util.Try[Int]] = None

scala> Await result (res1, duration.Duration("60 seconds"))
Extra work before the job.
Job 7
res3: Int = 8

Yes, I need a minute to type that in.

som-snytt
  • 39,429
  • 2
  • 47
  • 129