ThaipedActor is alive
This commit is contained in:
parent
3a255ef083
commit
c312fb7c57
1 changed files with 44 additions and 16 deletions
|
|
@ -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]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue