summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraleksandar <aleksandar@lampmac14.epfl.ch>2012-01-24 15:22:27 +0100
committeraleksandar <aleksandar@lampmac14.epfl.ch>2012-01-24 15:22:27 +0100
commit85daadef89a9ed5c3901a5822221366ee6746d49 (patch)
tree596e2b7ba3e6b49828ccce0aa7b6af02bf77a903
parent645cb791cf032d464de6a3a0d8e7ee1ae4ffe73c (diff)
downloadscala-85daadef89a9ed5c3901a5822221366ee6746d49.tar.gz
scala-85daadef89a9ed5c3901a5822221366ee6746d49.tar.bz2
scala-85daadef89a9ed5c3901a5822221366ee6746d49.zip
Removed the nondeterministic implicit. Added rescue.
-rw-r--r--src/library/scala/concurrent/ExecutionContext.scala7
-rw-r--r--src/library/scala/concurrent/Future.scala97
-rw-r--r--src/library/scala/concurrent/Promise.scala10
-rw-r--r--src/library/scala/concurrent/akka/Promise.scala4
-rw-r--r--src/library/scala/concurrent/default/TaskImpl.scala7
-rw-r--r--src/library/scala/concurrent/package.scala3
6 files changed, 74 insertions, 54 deletions
diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala
index 260d4cb54d..5ad9265f59 100644
--- a/src/library/scala/concurrent/ExecutionContext.scala
+++ b/src/library/scala/concurrent/ExecutionContext.scala
@@ -16,7 +16,6 @@ import scala.util.Duration
import scala.concurrent.forkjoin.{ ForkJoinPool, RecursiveTask => FJTask, RecursiveAction, ForkJoinWorkerThread }
import scala.collection.generic.CanBuildFrom
import collection._
-import annotation.implicitNotFound
@@ -90,8 +89,7 @@ trait ExecutionContext {
/** TODO some docs
*
*/
- @implicitNotFound(msg = "Calling this method yields non-deterministic programs.")
- def any[T](futures: Traversable[Future[T]])(implicit nondet: NonDeterministic): Future[T] = {
+ def any[T](futures: Traversable[Future[T]]): Future[T] = {
val p = promise[T]
val completeFirst: Either[Throwable, T] => Unit = elem => p tryComplete elem
@@ -103,8 +101,7 @@ trait ExecutionContext {
/** TODO some docs
*
*/
- @implicitNotFound(msg = "Calling this method yields non-deterministic programs.")
- def find[T](futures: Traversable[Future[T]])(predicate: T => Boolean)(implicit nondet: NonDeterministic): Future[Option[T]] = {
+ def find[T](futures: Traversable[Future[T]])(predicate: T => Boolean): Future[Option[T]] = {
if (futures.isEmpty) Promise.kept[Option[T]](None).future
else {
val result = promise[Option[T]]
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index a22f67d45d..2ad24c052d 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -24,7 +24,6 @@ import scala.annotation.tailrec
import scala.collection.mutable.Stack
import scala.collection.mutable.Builder
import scala.collection.generic.CanBuildFrom
-import scala.annotation.implicitNotFound
@@ -60,7 +59,10 @@ import scala.annotation.implicitNotFound
* as the cause.
* If a future is failed with a `scala.runtime.NonLocalReturnControl`,
* it is completed with a value instead from that throwable instead instead.
- *
+ *
+ * @define nonDeterministic
+ * Note: using this method yields nondeterministic dataflow programs.
+ *
* @define forComprehensionExamples
* Example:
*
@@ -173,31 +175,6 @@ self =>
/* Monadic operations */
- /** Creates a new future that will handle any matching throwable that this
- * future might contain. If there is no match, or if this future contains
- * a valid result then the new future will contain the same.
- *
- * 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
- * }}}
- */
- def recover[U >: T](pf: PartialFunction[Throwable, U]): Future[U] = {
- val p = newPromise[U]
-
- onComplete {
- case Left(t) if pf isDefinedAt t =>
- try { p success pf(t) }
- catch { case t: Throwable => p complete resolver(t) }
- case otherwise => p complete otherwise
- }
-
- p.future
- }
-
/** Asynchronously processes the value in the future once the value becomes available.
*
* Will not be called if the future fails.
@@ -324,14 +301,69 @@ self =>
p.future
}
+ /** Creates a new future that will handle any matching throwable that this
+ * future might contain. If there is no match, or if this future contains
+ * a valid result then the new future will contain the same.
+ *
+ * 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
+ * }}}
+ */
+ def recover[U >: T](pf: PartialFunction[Throwable, U]): Future[U] = {
+ val p = newPromise[U]
+
+ onComplete {
+ case Left(t) if pf isDefinedAt t =>
+ try { p success pf(t) }
+ catch { case t: Throwable => p complete resolver(t) }
+ case otherwise => p complete otherwise
+ }
+
+ p.future
+ }
+
+ /** Creates a new future that will handle any matching throwable that this
+ * future might contain by assigning it a value of another future.
+ *
+ * If there is no match, or if this future contains
+ * a valid result then the new future will contain the same result.
+ *
+ * Example:
+ *
+ * {{{
+ * val f = future { Int.MaxValue }
+ * future (6 / 0) rescue { case e: ArithmeticException => f } // result: Int.MaxValue
+ * }}}
+ */
+ def rescue[U >: T](pf: PartialFunction[Throwable, Future[U]]): Future[U] = {
+ val p = newPromise[U]
+
+ onComplete {
+ case Left(t) if pf isDefinedAt t =>
+ try {
+ pf(t) onComplete {
+ case Left(t) => p failure t
+ case Right(v) => p success v
+ }
+ } catch {
+ case t: Throwable => p complete resolver(t)
+ }
+ case otherwise => p complete otherwise
+ }
+
+ p.future
+ }
+
/** Creates a new future which holds the result of this future if it was completed successfully, or, if not,
* the result of the `that` future if `that` is completed successfully.
* If both futures are failed, the resulting future holds the throwable object of the first future.
*
* Using this method will not cause concurrent programs to become nondeterministic.
*
- *
- *
* Example:
* {{{
* val f = future { sys.error("failed") }
@@ -367,8 +399,7 @@ self =>
* await(0) h // evaluates to either 5 or throws a runtime exception
* }}}
*/
- @implicitNotFound(msg = "Calling this method yields non-deterministic programs.")
- def either[U >: T](that: Future[U])(implicit nondet: NonDeterministic): Future[U] = {
+ def either[U >: T](that: Future[U]): Future[U] = {
val p = self.newPromise[U]
val completePromise: PartialFunction[Either[Throwable, U], _] = {
@@ -402,9 +433,9 @@ object Future {
// move this to future companion object
@inline def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = executor.future(body)
- def any[T](futures: Traversable[Future[T]])(implicit ec: ExecutionContext, nondet: NonDeterministic): Future[T] = ec.any(futures)
+ def any[T](futures: Traversable[Future[T]])(implicit ec: ExecutionContext): Future[T] = ec.any(futures)
- def find[T](futures: Traversable[Future[T]])(predicate: T => Boolean)(implicit ec: ExecutionContext, nondet: NonDeterministic): Future[Option[T]] = ec.find(futures)(predicate)
+ def find[T](futures: Traversable[Future[T]])(predicate: T => Boolean)(implicit ec: ExecutionContext): Future[Option[T]] = ec.find(futures)(predicate)
}
diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala
index 669025699a..acc02fba5f 100644
--- a/src/library/scala/concurrent/Promise.scala
+++ b/src/library/scala/concurrent/Promise.scala
@@ -10,7 +10,6 @@ package scala.concurrent
-import scala.annotation.implicitNotFound
@@ -51,8 +50,7 @@ trait Promise[T] {
*
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
- @implicitNotFound(msg = "Calling this method yields non-deterministic programs.")
- def tryComplete(result: Either[Throwable, T])(implicit nondet: NonDeterministic): Boolean
+ def tryComplete(result: Either[Throwable, T]): Boolean
/** Completes this promise with the specified future, once that future is completed.
*
@@ -79,8 +77,7 @@ trait Promise[T] {
*
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
- @implicitNotFound(msg = "Calling this method yields non-deterministic programs.")
- def trySuccess(value: T)(implicit nondet: NonDeterministic): Boolean = tryComplete(Right(value))(nonDeterministicEvidence)
+ def trySuccess(value: T): Boolean = tryComplete(Right(value))
/** Completes the promise with an exception.
*
@@ -98,8 +95,7 @@ trait Promise[T] {
*
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
- @implicitNotFound(msg = "Calling this method yields non-deterministic programs.")
- def tryFailure(t: Throwable)(implicit nondet: NonDeterministic): Boolean = tryComplete(Left(t))(nonDeterministicEvidence)
+ def tryFailure(t: Throwable): Boolean = tryComplete(Left(t))
/** Wraps a `Throwable` in an `ExecutionException` if necessary. TODO replace with `resolver` from scala.concurrent
*
diff --git a/src/library/scala/concurrent/akka/Promise.scala b/src/library/scala/concurrent/akka/Promise.scala
index 340b40bf74..923d5baf6d 100644
--- a/src/library/scala/concurrent/akka/Promise.scala
+++ b/src/library/scala/concurrent/akka/Promise.scala
@@ -144,7 +144,7 @@ object Promise {
@inline
protected final def getState: FState[T] = updater.get(this)
- def tryComplete(value: Either[Throwable, T])(implicit nd: NonDeterministic): Boolean = {
+ def tryComplete(value: Either[Throwable, T]): Boolean = {
val callbacks: List[Either[Throwable, T] => Any] = {
try {
@tailrec
@@ -211,7 +211,7 @@ object Promise {
final class KeptPromise[T](suppliedValue: Either[Throwable, T])(implicit val executor: ExecutionContextImpl) extends Promise[T] {
val value = Some(resolve(suppliedValue))
- def tryComplete(value: Either[Throwable, T])(implicit nondet: NonDeterministic): Boolean = false
+ def tryComplete(value: Either[Throwable, T]): Boolean = false
def onComplete[U](func: Either[Throwable, T] => U): this.type = {
val completedAs = value.get
diff --git a/src/library/scala/concurrent/default/TaskImpl.scala b/src/library/scala/concurrent/default/TaskImpl.scala
index 227d9d48cd..3e52d79894 100644
--- a/src/library/scala/concurrent/default/TaskImpl.scala
+++ b/src/library/scala/concurrent/default/TaskImpl.scala
@@ -7,7 +7,6 @@ import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
import scala.concurrent.forkjoin.{ ForkJoinPool, RecursiveAction, ForkJoinWorkerThread }
import scala.util.Duration
import scala.annotation.tailrec
-import scala.concurrent.NonDeterministic
@@ -88,12 +87,12 @@ extends Promise[T] with Future[T] with Completable[T] {
case _ => null
}
- def tryComplete(r: Either[Throwable, T])(implicit nd: NonDeterministic) = r match {
+ def tryComplete(r: Either[Throwable, T]) = r match {
case Left(t) => tryFailure(t)
case Right(v) => trySuccess(v)
}
- override def trySuccess(value: T)(implicit nd: NonDeterministic): Boolean = {
+ override def trySuccess(value: T): Boolean = {
val cbs = tryCompleteState(Success(value))
if (cbs == null)
false
@@ -106,7 +105,7 @@ extends Promise[T] with Future[T] with Completable[T] {
}
}
- override def tryFailure(t: Throwable)(implicit nd: NonDeterministic): Boolean = {
+ override def tryFailure(t: Throwable): Boolean = {
val wrapped = wrap(t)
val cbs = tryCompleteState(Failure(wrapped))
if (cbs == null)
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index 9f3238ddb2..6c1e323595 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -119,9 +119,6 @@ package object concurrent {
* cannot send requests to a server thread through regular promises and futures).
*/
object nondeterministic {
-
- implicit val nonDeterministicEvidence = new NonDeterministic {}
-
}
final class DurationOps private[concurrent] (x: Int) {