diff --git a/akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala b/akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala index 578f557871..097912601a 100644 --- a/akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala @@ -103,6 +103,32 @@ class ActorDSLSpec extends AkkaSpec { i.receive() must be("hi") } + "support becomeStacked" in { + //#becomeStacked + val a = actor(new Act { + become { // this will replace the initial (empty) behavior + case "info" ⇒ sender ! "A" + case "switch" ⇒ + becomeStacked { // this will stack upon the "A" behavior + case "info" ⇒ sender ! "B" + case "switch" ⇒ unbecome() // return to the "A" behavior + } + case "lobotomize" => unbecome() // OH NOES: Actor.emptyBehavior + } + }) + //#becomeStacked + + implicit def sender = testActor + a ! "info" + expectMsg("A") + a ! "switch" + a ! "info" + expectMsg("B") + a ! "switch" + a ! "info" + expectMsg("A") + } + "support setup/teardown" in { //#simple-start-stop val a = actor(new Act { @@ -188,7 +214,7 @@ class ActorDSLSpec extends AkkaSpec { become { case 1 ⇒ stash() case 2 ⇒ - testActor ! 2; unstashAll(); become { + testActor ! 2; unstashAll(); becomeStacked { case 1 ⇒ testActor ! 1; unbecome() } } diff --git a/akka-actor/src/main/scala/akka/actor/dsl/Creators.scala b/akka-actor/src/main/scala/akka/actor/dsl/Creators.scala index 98ab610502..a9515f3000 100644 --- a/akka-actor/src/main/scala/akka/actor/dsl/Creators.scala +++ b/akka-actor/src/main/scala/akka/actor/dsl/Creators.scala @@ -29,7 +29,9 @@ trait Creators { this: ActorDSL.type ⇒ * for quickly trying things out in the REPL. It makes the following keywords * available: * - * - `become` mapped to `context.become(_, discardOld = false)` + * - `become` mapped to `context.become(_, discardOld = true)` + * + * - `becomeStacked` mapped to `context.become(_, discardOld = false)` * * - `unbecome` mapped to `context.unbecome` * @@ -87,7 +89,14 @@ trait Creators { this: ActorDSL.type ⇒ * stack is cleared upon restart. Use `unbecome()` to pop an element off * this stack. */ - def become(r: Receive) = context.become(r, discardOld = false) + def becomeStacked(r: Receive) = context.become(r, discardOld = false) + + /** + * Replace the behavior at the top of the behavior stack for this actor. The + * stack is cleared upon restart. Use `unbecome()` to pop an element off + * this stack or `becomeStacked()` to push a new element on top of it. + */ + def become(r: Receive) = context.become(r, discardOld = true) /** * Pop the active behavior from the behavior stack of this actor. This stack diff --git a/akka-docs/rst/scala/actors.rst b/akka-docs/rst/scala/actors.rst index e81f744952..5a4be2cc58 100644 --- a/akka-docs/rst/scala/actors.rst +++ b/akka-docs/rst/scala/actors.rst @@ -174,6 +174,17 @@ form of the ``implicit val context: ActorContext``. Outside of an actor, you have to either declare an implicit :class:`ActorSystem`, or you can give the factory explicitly (see further below). +The two possible ways of issuing a ``context.become`` (replacing or adding the +new behavior) are offered separately to enable a clutter-free notation of +nested receives: + +.. includecode:: ../../../akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala#becomeStacked + +Please note that calling ``unbecome`` more often than ``becomeStacked`` results +in the original behavior being installed, which in case of the :class:`Act` +trait is the empty behavior (the outer ``become`` just replaces it during +construction). + Life-cycle hooks are also exposed as DSL elements (see `Start Hook`_ and `Stop Hook`_ below), where later invocations of the methods shown below will replace the contents of the respective hooks: