From c312fb7c574d06041b8149ebf09c1cfa5da2bc13 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 18 May 2011 10:04:25 +0200 Subject: [PATCH] ThaipedActor is alive --- .../main/scala/akka/actor/ThaipedActor.scala | 60 ++++++++++++++----- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/akka-typed-actor/src/main/scala/akka/actor/ThaipedActor.scala b/akka-typed-actor/src/main/scala/akka/actor/ThaipedActor.scala index 3df963d734..309e945755 100644 --- a/akka-typed-actor/src/main/scala/akka/actor/ThaipedActor.scala +++ b/akka-typed-actor/src/main/scala/akka/actor/ThaipedActor.scala @@ -1,15 +1,29 @@ package akka.actor import java.lang.reflect.{Method, InvocationHandler, Proxy} -import akka.dispatch.Future import akka.japi.{Creator, Option => JOption} import akka.actor.Actor.{actorOf, futureToAnyOptionAsTypedOption} +import akka.dispatch.{AlreadyCompletedFuture, Future} -trait T { +trait Foo { + def pigdog(): String + def futurePigdog(): Future[String] + def futurePigdog(delay: Long): Future[String] + + def optionPigdog(): Option[String] } -trait TImpl { +class Bar extends Foo { + def pigdog = "Bar" + + def futurePigdog(): Future[String] = new AlreadyCompletedFuture(Right(pigdog)) + def futurePigdog(delay: Long): Future[String] = { + Thread.sleep(delay) + futurePigdog + } + + def optionPigdog(): Option[String] = Some(pigdog) } @@ -18,47 +32,58 @@ object ThaipedActor { class ThaipedActor[TI](createInstance: => TI) extends Actor { val currentInstance = createInstance def receive = { - case (method: Method, args: Array[AnyRef]) => method.getReturnType match { + case Invocation(method, args) => + + def invokeMethod(): AnyRef = args match { + case null => method.invoke(currentInstance) + case some => method.invoke(currentInstance, some:_*) + } + + + method.getReturnType match { case c if c.isAssignableFrom(Void.TYPE) => //Handle sendOneWay - method.invoke(currentInstance, args) + invokeMethod() case c if c.isAssignableFrom(classOf[Future[_]]) => //Handle non-blocking sends - val r = method.invoke(currentInstance, args).asInstanceOf[Future[Any]] + val r = invokeMethod().asInstanceOf[Future[Any]] self.senderFuture.get completeWith r case c if c.isAssignableFrom(classOf[JOption[_]]) => //Handle Java options returns - self reply method.invoke(currentInstance, args) + self reply invokeMethod() case c if c.isAssignableFrom(classOf[Option[_]]) => //Handle Scala options returns - self reply method.invoke(currentInstance, args) + self reply invokeMethod() case _ => //Handle blocking request-reply sends - self reply method.invoke(currentInstance, args) + self reply invokeMethod() } } } + case class Invocation(method: Method, args: Array[AnyRef]) + protected[akka] def createInvocationHandler(actor: ActorRef): InvocationHandler = new InvocationHandler { def invoke(proxy: AnyRef, method: Method, args: Array[AnyRef]): AnyRef = method.getName match { - case "equals" | "hashCode" => method.invoke(proxy, args) + case "toString" => actor.toString + case "equals" => if (proxy eq args(0)) java.lang.Boolean.TRUE else java.lang.Boolean.FALSE case _ => method.getReturnType match { case c if c.isAssignableFrom(Void.TYPE) => //Handle sendOneWay - actor ! ((method, args)) + actor ! Invocation(method, args) null case c if c.isAssignableFrom(classOf[Future[_]]) => //Handle non-blocking sends - actor !!! ((method, args)) + actor !!! Invocation(method, args) case c if c.isAssignableFrom(classOf[JOption[_]]) => //Handle Java options returns - (actor !!! ((method, args))).as[JOption[Any]] match { + (actor !!! Invocation(method, args)).as[JOption[Any]] match { case Some(null) => JOption.none[Any] case Some(joption) => joption case None => JOption.none[Any] } case c if c.isAssignableFrom(classOf[Option[_]]) => //Handle Scala options returns - (actor !!! ((method, args))).as[AnyRef] match { + (actor !!! Invocation(method, args)).as[AnyRef] match { case Some(null) => None case Some(option) => option case None => None } case _ => //Handle blocking request-reply sends - (actor !!! ((method, args))).get + (actor !!! Invocation(method, args)).get } } } @@ -69,7 +94,10 @@ object ThaipedActor { def thaipedActorOf[T,TI <: T](interface: Class[T], impl: Creator[TI], loader: ClassLoader): T = newThaipedActor(interface, impl.create, loader) + def thaipedActorOf[T : Manifest, TI <: T](impl: Creator[TI], loader: ClassLoader): T = + newThaipedActor[T,TI](implicitly[Manifest[T]].erasure.asInstanceOf[Class[T]], impl, loader) - protected def newThaipedActor[T, TI <: T](interface: Class[T], impl: => TI, loader: ClassLoader = Thread.currentThread.getContextClassLoader): T = + + protected def newThaipedActor[T, TI <: T](interface: Class[T], impl: => TI, loader: ClassLoader): T = Proxy.newProxyInstance(loader, Array[Class[_]](interface), createInvocationHandler(actorOf(new ThaipedActor[TI](impl)).start)).asInstanceOf[T] } \ No newline at end of file