Search code examples
scalafutureexecutionsystemtime

When scala.concurrent.Future's execution starts?


Of course one could collect the system time at the first line of the Future's body. But:

Is it possible to know that time without having access to the future's code. (In my case the method returning the future is to be provided by the user of the 'framework'.)

def f: Future[Int] = ...

def magicTimePeak: Long = ???

Solution

  • The Future itself doesn't really know this (nor was it designed to care). It's all up to the executor when the code will actually be executed. This depends on whether or not a thread is immediately available, and if not, when one becomes available.


    You could wrap Future, to keep track of it, I suppose. It would involve creating an underlying Future with a closure that changes a mutable var within the wrapped class. Since you just want a Long, it would have to default to zero if the Future hasn't begun executing, though it would be trivial to change this to Option[Date] or something.

    class WrappedFuture[A](thunk: => A)(implicit ec: ExecutionContext) {
    
        var started: Long = 0L
    
        val underlying = Future {
            started = System.nanoTime / 1000000 // milliseconds
            thunk
        }
    
    }
    

    To show that it works, create a fixed thread pool with one thread, then feed it a blocking task for say, 5 seconds. Then, create a WrappedFuture, and check it's started value later. Note the difference in the logged times.

    import java.util.concurrent.Executors
    import scala.concurrent._
    val executorService = Executors.newFixedThreadPool(1)
    implicit val ec = ExecutionContext.fromExecutorService(executorService)
    
    scala> println("Before blocked: " + System.nanoTime / 1000000)
    Before blocked: 13131636
    
    scala> val blocker = Future(Thread.sleep(5000))
    blocker: scala.concurrent.Future[Unit] = scala.concurrent.impl.Promise$DefaultPromise@7e5d9a50
    
    scala> val f = new WrappedFuture(1)
    f: WrappedFuture[Int] = WrappedFuture@4c4748bf
    
    scala> f.started
    res13: Long = 13136779 // note the difference in time of about 5000 ms from earlier
    

    If you don't control the creation of the Future, however, there is nothing you can do to figure out when it started.