diff --git a/akka-actor/src/main/scala/akka/dispatch/Future.scala b/akka-actor/src/main/scala/akka/dispatch/Future.scala index 96c8f5e252..11e64e2683 100644 --- a/akka-actor/src/main/scala/akka/dispatch/Future.scala +++ b/akka-actor/src/main/scala/akka/dispatch/Future.scala @@ -377,6 +377,37 @@ sealed trait Future[+T] extends japi.Future[T] { */ def await(atMost: Duration): Future[T] + /** + * Await completion of this Future and return its value if it conforms to A's + * erased type. Will throw a ClassCastException if the value does not + * conform, or any exception the Future was completed with. Will return None + * in case of a timeout. + */ + def as[A](implicit m: Manifest[A]): Option[A] = { + try await catch { case _: FutureTimeoutException ⇒ } + value match { + case None ⇒ None + case Some(Left(ex)) ⇒ throw ex + case Some(Right(v)) ⇒ Some(BoxedType(m.erasure).cast(v).asInstanceOf[A]) + } + } + + /** + * Await completion of this Future and return its value if it conforms to A's + * erased type, None otherwise. Will throw any exception the Future was + * completed with. Will return None in case of a timeout. + */ + def asSilently[A](implicit m: Manifest[A]): Option[A] = { + try await catch { case _: FutureTimeoutException ⇒ } + value match { + case None ⇒ None + case Some(Left(ex)) ⇒ throw ex + case Some(Right(v)) ⇒ + try Some(BoxedType(m.erasure).cast(v).asInstanceOf[A]) + catch { case _: ClassCastException ⇒ None } + } + } + /** * Tests whether this Future has been completed. */ diff --git a/akka-actor/src/main/scala/akka/package.scala b/akka-actor/src/main/scala/akka/package.scala index e96a1eddbf..b122d9297b 100644 --- a/akka-actor/src/main/scala/akka/package.scala +++ b/akka-actor/src/main/scala/akka/package.scala @@ -12,17 +12,6 @@ package object akka { */ implicit def toAnyOptionAsTypedOption(anyOption: Option[Any]) = new AnyOptionAsTypedOption(anyOption) - /** - * Implicitly converts the given Future[_] to a AnyOptionAsTypedOption which offers the method as[T] - * to convert an Option[Any] to an Option[T]. - * This means that the following code is equivalent: - * (actor ? "foo").as[Int] (Recommended) - */ - implicit def futureToAnyOptionAsTypedOption(anyFuture: Future[_]) = new AnyOptionAsTypedOption({ - try { anyFuture.await } catch { case t: FutureTimeoutException ⇒ } - anyFuture.resultOrException - }) - private[akka] class AnyOptionAsTypedOption(anyOption: Option[Any]) { /** * Convenience helper to cast the given Option of Any to an Option of the given type. Will throw a ClassCastException diff --git a/akka-docs/scala/actors.rst b/akka-docs/scala/actors.rst index 69ebc4edbc..068575a04a 100644 --- a/akka-docs/scala/actors.rst +++ b/akka-docs/scala/actors.rst @@ -287,8 +287,11 @@ processing another message on this actor). For this purpose, there is the method :meth:`Future.as[T]` which waits until either the future is completed or its timeout expires, whichever comes first. The result is then inspected and returned as :class:`Some[T]` if it was -normally completed and the answer’s runtime type matches the desired type; in -all other cases :class:`None` is returned. +normally completed and the answer’s runtime type matches the desired type; if +the future contains an exception or the value cannot be cast to the desired +type, it will throw the exception or a :class:`ClassCastException` (if you want +to get :obj:`None` in the latter case, use :meth:`Future.asSilently[T]`). In +case of a timeout, :obj:`None` is returned. .. code-block:: scala