Skip to content

Feature request: deferred-start Futures #108

@mbovel

Description

@mbovel

Could we add a Future constructor in the gears library that allows computations to be defined without starting them immediately?

This would enable defining a DAG of inter-dependent asynchronous tasks in an arbitrary order. For example, in pseudo-code:

t0 = t1.result + t2.result
t1 = t3.result + 4
t2 = t3.result + 2
t3 = 1

The key requirement here is that tasks should not execute until explicitly triggered, allowing dependencies to be set up first.

Below is a working user-land implementation:

// async-lazy.scala
//> using dep "ch.epfl.lamp::gears::0.2.0"

import gears.async.{Future, Async}
import gears.async.default.given
import Async.await

final class AsyncLazy[T](body: (Async, Async.Spawn) ?=> T):
  private var _future: Future[T] | Null = null

  def get()(using Async, Async.Spawn): T =
    if _future == null then
      this.synchronized:
        if _future == null then
          _future = Future(body)
    _future.nn.await

@main def main =
  println("starting")
  val a = new Array(4)
  a(0) = AsyncLazy:
    println("compute a(0)")
    a(1).get() + a(2).get()
  a(1) = AsyncLazy:
    println("compute a(1)")
    a(3).get() + 4
  a(2) = AsyncLazy:
    println("compute a(2)")
    a(3).get() + 2
  a(3) = AsyncLazy:
    println("compute a(3)")
    1

  Async.blocking:
    println(a(0).get())

Running this code produces the following output:

$ scala -S 3.5.1 --server=false async-lazy.scala
starting
compute a(0)
compute a(1)
compute a(3)
compute a(2)
8

I believe a dedicated feature in gears could achieve something similar more efficiently, by saving the extra synchronization.

A Future constructor could return a deferred-start Future, of which the execution begins only when explicitly triggered. In the example above, one could then loop over Futures to start them after they have all been defined.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions