Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions library/src/scala/concurrent/BatchingExecutor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,30 +60,38 @@ private[concurrent] object BatchingExecutorStatics {
* When you implement this trait for async executors like thread pools,
* you're going to need to implement it something like the following:
*
* ```
* final override def submitAsync(runnable: Runnable): Unit =
* super[SuperClass].execute(runnable) // To prevent reentrancy into `execute`
* ```scala sc:compile
* import java.util.concurrent.Executor
*
* final class AsyncBatchingExecutor(delegate: Executor)
* extends ExecutionContextExecutor
* with BatchingExecutor {
* final override def submitForExecution(runnable: Runnable): Unit =
* delegate.execute(runnable)
*
* final override def execute(runnable: Runnable): Unit =
* if (runnable.isInstanceOf[Batchable]) // Or other logic
* submitAsyncBatched(runnable)
* else
* submitAsync(runnable)
* final override def execute(runnable: Runnable): Unit =
* if (runnable.isInstanceOf[Batchable])
* submitAsyncBatched(runnable)
* else
* submitForExecution(runnable)
*
* final override def reportFailure(cause: Throwable): Unit = …
* final override def reportFailure(cause: Throwable): Unit = ()
* }
* ```
*
* And if you want to implement if for a sync, trampolining, executor you're
* going to implement it something like this:
*
* ```
* final override def submitAsync(runnable: Runnable): Unit = ()
* ```scala sc:compile
* final class TrampoliningExecutor extends ExecutionContextExecutor with BatchingExecutor {
* final override def submitForExecution(runnable: Runnable): Unit = ()
*
* final override def execute(runnable: Runnable): Unit =
* submitSyncBatched(runnable) // You typically will want to batch everything
* final override def execute(runnable: Runnable): Unit =
* submitSyncBatched(runnable)
*
* final override def reportFailure(cause: Throwable): Unit =
* ExecutionContext.defaultReporter(cause) // Or choose something more fitting
* final override def reportFailure(cause: Throwable): Unit =
* ExecutionContext.defaultReporter(cause)
* }
* ```
*/
private[concurrent] trait BatchingExecutor extends Executor {
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/concurrent/BlockContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import scala.language.`2.13`
*
* Typically, you'll want to chain to the previous `BlockContext`,
* like this:
* ```
* ```scala sc:compile
* val oldContext = BlockContext.current
* val myContext = new BlockContext {
* override def blockOn[T](thunk: => T)(implicit permission: CanAwait): T = {
Expand Down
32 changes: 18 additions & 14 deletions library/src/scala/concurrent/ExecutionContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ object ExecutionContext {
* in case the `opportunistic` field is missing (example below). The resulting `ExecutionContext` has batching
* behavior in all Scala 2.13 versions (`global` is batching in 2.13.0-3).
*
* ```
* ```scala sc:compile
* implicit val ec: scala.concurrent.ExecutionContext = try {
* scala.concurrent.ExecutionContext.getClass
* .getDeclaredMethod("opportunistic")
Expand All @@ -174,19 +174,23 @@ object ExecutionContext {
* 1. Writing a Scala `object` in the `scala` package (example below).
* 1. Writing a Java source file. This works because `private[scala]` is emitted as `public` in Java bytecode.
*
* ```
* // Option 1
* ```scala sc:compile
* import scala.language.reflectiveCalls
*
* type ExecutionContextCompanionApi = AnyRef {
* def opportunistic: scala.concurrent.ExecutionContextExecutor
* }
*
* implicit val ec: scala.concurrent.ExecutionContext =
* (scala.concurrent.ExecutionContext:
* {def opportunistic: scala.concurrent.ExecutionContextExecutor}
* ).opportunistic
*
* // Option 2
* package scala {
* object OpportunisticEC {
* implicit val ec: scala.concurrent.ExecutionContext =
* scala.concurrent.ExecutionContext.opportunistic
* }
* scala.concurrent.ExecutionContext
* .asInstanceOf[ExecutionContextCompanionApi]
* .opportunistic
* ```
*
* ```scala sc:compile
* object OpportunisticEC {
* implicit val ec: scala.concurrent.ExecutionContext =
* scala.concurrent.ExecutionContext.opportunistic
* }
* ```
*
Expand Down Expand Up @@ -252,7 +256,7 @@ object ExecutionContext {
* If it is guaranteed that none of the executed tasks are blocking, a single-threaded `ExecutorService`
* can be used to create an `ExecutionContext` as follows:
*
* ```
* ```scala sc:compile
* import java.util.concurrent.Executors
* val ec = ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())
* ```
Expand Down
94 changes: 61 additions & 33 deletions library/src/scala/concurrent/Future.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import scala.concurrent.impl.Promise.DefaultPromise
* Computations are executed using an `ExecutionContext`, which is usually supplied implicitly,
* and which is commonly backed by a thread pool.
*
* ```
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val s = "Hello"
* val f: Future[String] = Future {
Expand Down Expand Up @@ -79,7 +79,8 @@ import scala.concurrent.impl.Promise.DefaultPromise
* @define forComprehensionExamples
* Example:
*
* ```
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val f = Future { 5 }
* val g = Future { 3 }
* val h = for {
Expand All @@ -90,7 +91,10 @@ import scala.concurrent.impl.Promise.DefaultPromise
*
* is translated to:
*
* ```
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val f = Future { 5 }
* val g = Future { 3 }
* f flatMap { (x: Int) => g map { (y: Int) => x + y } }
* ```
*
Expand Down Expand Up @@ -237,9 +241,10 @@ trait Future[+T] extends Awaitable[T] {
*
* Example:
*
* ```
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val f = Future { "The future" }
* val g = f map { x: String => x + " is now!" }
* val g = f.map { (x: String) => x + " is now!" }
* ```
*
* Note that a for comprehension involving a `Future`
Expand Down Expand Up @@ -291,7 +296,9 @@ trait Future[+T] extends Awaitable[T] {
* If the current future fails, then the resulting future also fails.
*
* Example:
* ```
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* import scala.concurrent.duration.Duration
* val f = Future { 5 }
* val g = f filter { _ % 2 == 1 }
* val h = f filter { _ % 2 == 0 }
Expand Down Expand Up @@ -329,7 +336,9 @@ trait Future[+T] extends Awaitable[T] {
* If the current future fails, then the resulting future also fails.
*
* Example:
* ```
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* import scala.concurrent.duration.Duration
* val f = Future { -5 }
* val g = f collect {
* case x if x < 0 => -x
Expand Down Expand Up @@ -361,10 +370,11 @@ trait Future[+T] extends Awaitable[T] {
*
* Example:
*
* ```
* Future (6 / 0) recover { case e: ArithmeticException => 0 } // result: 0
* Future (6 / 0) recover { case e: NotFoundException => 0 } // result: exception
* Future (6 / 2) recover { case e: ArithmeticException => 0 } // result: 3
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* Future(6 / 0).recover { case _: ArithmeticException => 0 } // result: 0
* Future(6 / 0).recover { case _: NoSuchElementException => 0 } // result: exception
* Future(6 / 2).recover { case _: ArithmeticException => 0 } // result: 3
* ```
*
* @tparam U the type of the returned `Future`
Expand All @@ -384,9 +394,10 @@ trait Future[+T] extends Awaitable[T] {
*
* Example:
*
* ```
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val f = Future { Int.MaxValue }
* Future (6 / 0) recoverWith { case e: ArithmeticException => f } // result: Int.MaxValue
* Future(6 / 0).recoverWith { case _: ArithmeticException => f } // result: Int.MaxValue
* ```
*
* @tparam U the type of the returned `Future`
Expand Down Expand Up @@ -454,7 +465,8 @@ trait Future[+T] extends Awaitable[T] {
* Using this method will not cause concurrent programs to become nondeterministic.
*
* Example:
* ```
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val f = Future { throw new RuntimeException("failed") }
* val g = Future { 5 }
* val h = f fallbackTo g
Expand Down Expand Up @@ -508,7 +520,9 @@ trait Future[+T] extends Awaitable[T] {
*
* The following example prints out `5`:
*
* ```
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* import scala.util.{Failure, Success}
* val f = Future { 5 }
* f andThen {
* case r => throw new RuntimeException("runtime exception")
Expand Down Expand Up @@ -689,10 +703,12 @@ object Future {
*
* The following expressions are equivalent:
*
* ```
* val f1 = Future(expr)
* val f2 = Future.unit.map(_ => expr)
* val f3 = Future.unit.transform(_ => Success(expr))
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* import scala.util.Success
* val f1 = Future(1 + 1)
* val f2 = Future.unit.map(_ => 1 + 1)
* val f3 = Future.unit.transform(_ => Success(1 + 1))
* ```
*
* The result becomes available once the asynchronous computation is completed.
Expand All @@ -709,10 +725,11 @@ object Future {
*
* The following expressions are semantically equivalent:
*
* ```
* val f1 = Future(expr).flatten
* val f2 = Future.delegate(expr)
* val f3 = Future.unit.flatMap(_ => expr)
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val f1 = Future(Future.successful(1 + 1)).flatten
* val f2 = Future.delegate(Future.successful(1 + 1))
* val f3 = Future.unit.flatMap(_ => Future.successful(1 + 1))
* ```
*
* The result becomes available once the resulting Future of the asynchronous computation is completed.
Expand Down Expand Up @@ -805,8 +822,10 @@ object Future {
* or the result of the fold.
*
* Example:
* ```
* val futureSum = Future.foldLeft(futures)(0)(_ + _)
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val futures = List(Future.successful(1), Future.successful(2), Future.successful(3))
* val futureSum = Future.foldLeft(futures)(0)(_ + _)
* ```
*
* @tparam T the type of the value of the input Futures
Expand All @@ -829,8 +848,10 @@ object Future {
* or the result of the fold.
*
* Example:
* ```
* val futureSum = Future.fold(futures)(0)(_ + _)
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val futures = List(Future.successful(1), Future.successful(2), Future.successful(3))
* val futureSum = Future.fold(futures)(0)(_ + _)
* ```
*
* @tparam T the type of the value of the input Futures
Expand All @@ -850,8 +871,10 @@ object Future {
* where the fold-zero is the result value of the first `Future` in the collection.
*
* Example:
* ```
* val futureSum = Future.reduce(futures)(_ + _)
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val futures = List(Future.successful(1), Future.successful(2), Future.successful(3))
* val futureSum = Future.reduce(futures)(_ + _)
* ```
* @tparam T the type of the value of the input Futures
* @tparam R the type of the value of the returned `Future`
Expand All @@ -869,8 +892,10 @@ object Future {
* where the zero is the result value of the first `Future`.
*
* Example:
* ```
* val futureSum = Future.reduceLeft(futures)(_ + _)
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val futures = List(Future.successful(1), Future.successful(2), Future.successful(3))
* val futureSum = Future.reduceLeft(futures)(_ + _)
* ```
* @tparam T the type of the value of the input Futures
* @tparam R the type of the value of the returned `Future`
Expand All @@ -889,8 +914,11 @@ object Future {
* This is useful for performing a parallel map. For example, to apply a function to all items of a list
* in parallel:
*
* ```
* val myFutureList = Future.traverse(myList)(x => Future(myFunc(x)))
* ```scala sc:compile
* import ExecutionContext.Implicits.global
* val myList = List(1, 2, 3)
* def myFunc(x: Int): Int = x + 1
* val myFutureList = Future.traverse(myList)(x => Future(myFunc(x)))
* ```
* @tparam A the type of the value inside the Futures in the collection
* @tparam B the type of the value of the returned `Future`
Expand Down
4 changes: 2 additions & 2 deletions library/src/scala/concurrent/duration/Deadline.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import scala.language.`2.13`
/** This class stores a deadline, as obtained via `Deadline.now` or the
* duration DSL:
*
* ```
* import scala.concurrent.duration._
* ```scala sc:compile
* import scala.concurrent.duration.*
* 3.seconds.fromNow
* ```
*
Expand Down
17 changes: 10 additions & 7 deletions library/src/scala/concurrent/duration/Duration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,11 @@ object Duration {
*
* <p/>
* Examples:
* ```
* import scala.concurrent.duration._
* ```scala sc:compile
* import scala.concurrent.duration.*
*
* val duration = Duration(100, MILLISECONDS)
* val duration = Duration(100, "millis")
* val sameDuration = Duration(100, "millis")
*
* duration.toNanos
* duration < 1.second
Expand All @@ -338,16 +338,18 @@ object Duration {
*
* <p/>
* Implicits are also provided for Int, Long and Double. Example usage:
* ```
* import scala.concurrent.duration._
* ```scala sc:compile
* import scala.concurrent.duration.*
*
* val duration = 100.millis
* ```
*
* ***The DSL provided by the implicit conversions always allows construction of finite durations, even for infinite Double inputs; use Duration.Inf instead.***
*
* Extractors, parsing and arithmetic are also included:
* ```
* ```scala sc:compile
* import scala.concurrent.duration.*
* import scala.language.postfixOps
* val d = Duration("1.2 µs")
* val Duration(length, unit) = 5 millis
* val d2 = d * 2.5
Expand Down Expand Up @@ -567,7 +569,8 @@ sealed abstract class Duration extends Serializable with Ordered[Duration] {
/** Returns duration which is equal to this duration but with a coarsest Unit, or self in case it is already the coarsest Unit
* <p/>
* Examples:
* ```
* ```scala sc:compile
* import scala.concurrent.duration.*
* Duration(60, MINUTES).toCoarsest // Duration(1, HOURS)
* Duration(1000, MILLISECONDS).toCoarsest // Duration(1, SECONDS)
* Duration(48, HOURS).toCoarsest // Duration(2, DAYS)
Expand Down
Loading
Loading