ThaipedActor is alive

This commit is contained in:
Viktor Klang 2011-05-18 10:04:25 +02:00
parent 3a255ef083
commit c312fb7c57

View file

@ -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]
}