diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala index 8a0d665d4d..ba177698e2 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorRefSpec.scala @@ -129,45 +129,45 @@ class ActorRefSpec extends WordSpec with MustMatchers { }) } - def refStackMustBeEmpty = ActorInstance.refStack.get.headOption must be === None + def contextStackMustBeEmpty = ActorInstance.contextStack.get.headOption must be === None - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new FailingOuterActor(actorOf(new InnerActor))) } - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new OuterActor(actorOf(new FailingInnerActor))) } - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new FailingInheritingOuterActor(actorOf(new InnerActor))) } - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new FailingOuterActor(actorOf(new FailingInheritingInnerActor))) } - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new FailingInheritingOuterActor(actorOf(new FailingInheritingInnerActor))) } - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new FailingInheritingOuterActor(actorOf(new FailingInnerActor))) } - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new OuterActor(actorOf(new InnerActor { @@ -175,31 +175,31 @@ class ActorRefSpec extends WordSpec with MustMatchers { }))) } - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new FailingOuterActor(actorOf(new FailingInheritingInnerActor))) } - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new OuterActor(actorOf(new FailingInheritingInnerActor))) } - refStackMustBeEmpty + contextStackMustBeEmpty intercept[akka.actor.ActorInitializationException] { actorOf(new OuterActor(actorOf({ new InnerActor; new InnerActor }))) } - refStackMustBeEmpty + contextStackMustBeEmpty (intercept[java.lang.IllegalStateException] { actorOf(new OuterActor(actorOf({ throw new IllegalStateException("Ur state be b0rked"); new InnerActor }))) }).getMessage must be === "Ur state be b0rked" - refStackMustBeEmpty + contextStackMustBeEmpty } "be serializable using Java Serialization on local node" in { diff --git a/akka-actor/src/main/scala/akka/actor/Actor.scala b/akka-actor/src/main/scala/akka/actor/Actor.scala index bc197fecb5..9f39106f3a 100644 --- a/akka-actor/src/main/scala/akka/actor/Actor.scala +++ b/akka-actor/src/main/scala/akka/actor/Actor.scala @@ -454,32 +454,35 @@ trait Actor { */ type Receive = Actor.Receive + /** + * Stores the context for this actor, including self, sender, and hotswap. + */ + @transient + private[akka] val actorContext: ActorContext = { + val contextStack = ActorInstance.contextStack.get + + def noContextError = { + throw new ActorInitializationException( + "\n\tYou cannot create an instance of " + getClass.getName + " explicitly using the constructor (new)." + + "\n\tYou have to use one of the factory methods to create a new actor. Either use:" + + "\n\t\t'val actor = Actor.actorOf[MyActor]', or" + + "\n\t\t'val actor = Actor.actorOf(new MyActor(..))'") + } + + if (contextStack.isEmpty) noContextError + val context = contextStack.head + if (context eq null) noContextError + ActorInstance.contextStack.set(contextStack.push(null)) + context + } + /** * Some[ActorRef] representation of the 'self' ActorRef reference. *
* Mainly for internal use, functions as the implicit sender references when invoking * the 'forward' function. */ - @transient - val someSelf: Some[ScalaActorRef with SelfActorRef] = { - val refStack = ActorInstance.refStack.get - if (refStack.isEmpty) throw new ActorInitializationException( - "\n\tYou can not create an instance of an " + getClass.getName + " explicitly using 'new MyActor'." + - "\n\tYou have to use one of the factory methods in the 'Actor' object to create a new actor." + - "\n\tEither use:" + - "\n\t\t'val actor = Actor.actorOf[MyActor]', or" + - "\n\t\t'val actor = Actor.actorOf(new MyActor(..))'") - - val ref = refStack.head - - if (ref eq null) - throw new ActorInitializationException("Trying to create an instance of " + getClass.getName + " outside of a wrapping 'actorOf'") - else { - // Push a null marker so any subsequent calls to new Actor doesn't reuse this actor ref - ActorInstance.refStack.set(refStack.push(null)) - Some(ref) - } - } + def someSelf: Some[ScalaActorRef with SelfActorRef] = Some(actorContext.self) /* * Option[ActorRef] representation of the 'self' ActorRef reference. @@ -515,7 +518,7 @@ trait Actor { * */ @transient - implicit val self = someSelf.get + implicit def self = someSelf.get /** * User overridable callback/setting. diff --git a/akka-actor/src/main/scala/akka/actor/ActorContext.scala b/akka-actor/src/main/scala/akka/actor/ActorContext.scala new file mode 100644 index 0000000000..f24f644484 --- /dev/null +++ b/akka-actor/src/main/scala/akka/actor/ActorContext.scala @@ -0,0 +1,13 @@ +/** + * Copyright (C) 2009-2011 Typesafe Inc.