aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/scala/async/Async.scala
blob: 5e2d62dc62e789dbc208ccec92e0b146c6e920b5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*
 * Copyright (C) 2012-2014 Typesafe Inc. <http://www.typesafe.com>
 */

package scala.async

import scala.language.experimental.macros
import scala.concurrent.{Future, ExecutionContext}
import scala.reflect.internal.annotations.compileTimeOnly

/**
 * Async blocks provide a direct means to work with [[scala.concurrent.Future]].
 *
 * For example, to use an API that fetches a web page to fetch
 * two pages and add their lengths:
 *
 * {{{
 *  import ExecutionContext.Implicits.global
 *  import scala.async.Async.{async, await}
 *
 *  def fetchURL(url: URL): Future[String] = ...
 *
 *  val sumLengths: Future[Int] = async {
 *    val body1 = fetchURL("http://scala-lang.org")
 *    val body2 = fetchURL("http://docs.scala-lang.org")
 *    await(body1).length + await(body2).length
 *  }
 * }}}
 *
 * Note that the in the following program, the second fetch does *not* start
 * until after the first. If you need to start tasks in parallel, you must do
 * so before `await`-ing a result.
 *
 * {{{
 *  val sumLengths: Future[Int] = async {
 *    await(fetchURL("http://scala-lang.org")).length + await(fetchURL("http://docs.scala-lang.org")).length
 *  }
 * }}}
 */
object Async {
  /**
   * Run the block of code `body` asynchronously. `body` may contain calls to `await` when the results of
   * a `Future` are needed; this is translated into non-blocking code.
   */
  def async[T](body: => T)(implicit execContext: ExecutionContext): Future[T] = macro internal.ScalaConcurrentAsync.asyncImpl[T]

  /**
   * Non-blocking await the on result of `awaitable`. This may only be used directly within an enclosing `async` block.
   *
   * Internally, this will register the remainder of the code in enclosing `async` block as a callback
   * in the `onComplete` handler of `awaitable`, and will *not* block a thread.
   */
  @compileTimeOnly("`await` must be enclosed in an `async` block")
  def await[T](awaitable: Future[T]): T = ??? // No implementation here, as calls to this are translated to `onComplete` by the macro.
}