summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVojin Jovanovic <vojin.jovanovic@epfl.ch>2012-01-27 14:39:54 +0100
committerVojin Jovanovic <vojin.jovanovic@epfl.ch>2012-01-27 14:39:54 +0100
commit9e7bbedac86e95e90212d8153d0501714fdc3c09 (patch)
tree682ec23bcba678bf25f1984699511d6b5c1ff50c
parentf814d40ea917592f78d2e8ca4c78f34ce4b5f297 (diff)
parent62f012c2bbd948a1922a9eafb13267dc45f8392c (diff)
downloadscala-9e7bbedac86e95e90212d8153d0501714fdc3c09.tar.gz
scala-9e7bbedac86e95e90212d8153d0501714fdc3c09.tar.bz2
scala-9e7bbedac86e95e90212d8153d0501714fdc3c09.zip
Merge branch 'execution-context' of https://github.com/phaller/scala into execution-context
-rw-r--r--src/library/scala/concurrent/Future.scala86
1 files changed, 66 insertions, 20 deletions
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index 2ad24c052d..1b20c91e49 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -149,27 +149,18 @@ self =>
* Blocking on this future returns a value if the original future is completed with an exception
* and throws a corresponding exception if the original future fails.
*/
- def failed: Future[Throwable] = new Future[Throwable] {
- def newPromise[S]: Promise[S] = self.newPromise
- def onComplete[U](func: Either[Throwable, Throwable] => U) = {
- self.onComplete {
- case Left(t) => func(Right(t))
- case Right(v) => func(Left(noSuchElem(v))) // do nothing
- }
- this
- }
- def await(atMost: Duration)(implicit canawait: CanAwait): Throwable = {
- var t: Throwable = null
- try {
- val res = self.await(atMost)
- t = noSuchElem(res)
- } catch {
- case t: Throwable => return t
- }
- throw t
- }
- private def noSuchElem(v: T) =
+ def failed: Future[Throwable] = {
+ def noSuchElem(v: T) =
new NoSuchElementException("Future.failed not completed with a throwable. Instead completed with: " + v)
+
+ val p = newPromise[Throwable]
+
+ onComplete {
+ case Left(t) => p success t
+ case Right(v) => p failure noSuchElem(v)
+ }
+
+ p.future
}
@@ -386,6 +377,61 @@ self =>
p.future
}
+ /** Applies the side-effecting function to the result of this future, and returns
+ * a new future with the result of this future.
+ *
+ * This method allows one to enforce that the callbacks are executed in a
+ * specified order.
+ *
+ * Note that if one of the chained `andThen` callbacks throws
+ * an exception, that exception is not propagated to the subsequent `andThen`
+ * callbacks. Instead, the subsequent `andThen` callbacks are given the original
+ * value of this future.
+ *
+ * The following example prints out `5`:
+ *
+ * {{{
+ * val f = future { 5 }
+ * f andThen {
+ * case r => sys.error("runtime exception")
+ * } andThen {
+ * case Left(t) => println(t)
+ * case Right(v) => println(v)
+ * }
+ * }}}
+ */
+ def andThen[U](pf: PartialFunction[Either[Throwable, T], U]): Future[T] = {
+ val p = newPromise[T]
+
+ onComplete {
+ case r =>
+ try if (pf isDefinedAt r) pf(r)
+ finally p complete r
+ }
+
+ p.future
+ }
+
+ /** Executes a piece of code once this future is completed, regardless of whether
+ * or not the future fails or succeeds, and returns a new future with the result of this
+ * future.
+ *
+ * This method allows one to enforce ordering.
+ *
+ * The below example always executes the `println` calls in order:
+ * {{{
+ * val f = future { 5 }
+ * f ensure {
+ * println("The value is available.")
+ * } ensure {
+ * println("The application can now end.")
+ * }
+ * }}}
+ */
+ def ensure[U](body: =>U): Future[T] = andThen {
+ case _ => body
+ }
+
/** Creates a new future which holds the result of either this future or `that` future, depending on
* which future was completed first.
*