Merge branch 'master' into wip-channels-∂π
This commit is contained in:
commit
1b331dc547
575 changed files with 8084 additions and 6947 deletions
|
|
@ -19,10 +19,10 @@ immediately available for reading by any thread (using ``get`` or ``apply``)
|
|||
without any messages.
|
||||
|
||||
Agents are reactive. The update actions of all Agents get interleaved amongst
|
||||
threads in a thread pool. At any point in time, at most one ``send`` action for
|
||||
threads in an ``ExecutionContext``. At any point in time, at most one ``send`` action for
|
||||
each Agent is being executed. Actions dispatched to an agent from another thread
|
||||
will occur in the order they were sent, potentially interleaved with actions
|
||||
dispatched to the same agent from other sources.
|
||||
dispatched to the same agent from other threads.
|
||||
|
||||
If an Agent is used within an enclosing transaction, then it will participate in
|
||||
that transaction. Agents are integrated with Scala STM - any dispatches made in
|
||||
|
|
@ -30,32 +30,33 @@ a transaction are held until that transaction commits, and are discarded if it
|
|||
is retried or aborted.
|
||||
|
||||
|
||||
Creating and stopping Agents
|
||||
Creating Agents
|
||||
============================
|
||||
|
||||
Agents are created by invoking ``Agent(value)`` passing in the Agent's initial
|
||||
value:
|
||||
value and providing an implicit ``ExecutionContext`` to be used for it, for these
|
||||
examples we're going to use the default global one, but YMMV:
|
||||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#create
|
||||
|
||||
Note that creating an Agent requires an implicit ``ActorSystem`` (for creating
|
||||
the underlying actors). See :ref:`actor-systems` for more information about
|
||||
actor systems. An ActorSystem can be in implicit scope when creating an Agent:
|
||||
Reading an Agent's value
|
||||
========================
|
||||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#create-implicit-system
|
||||
Agents can be dereferenced (you can get an Agent's value) by invoking the Agent
|
||||
with parentheses like this:
|
||||
|
||||
Or the ActorSystem can be passed explicitly when creating an Agent:
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#read-apply
|
||||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#create-explicit-system
|
||||
Or by using the get method:
|
||||
|
||||
An Agent will be running until you invoke ``close`` on it. Then it will be
|
||||
eligible for garbage collection (unless you hold on to it in some way).
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#read-get
|
||||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#close
|
||||
Reading an Agent's current value does not involve any message passing and
|
||||
happens immediately. So while updates to an Agent are asynchronous, reading the
|
||||
state of an Agent is synchronous.
|
||||
|
||||
|
||||
Updating Agents
|
||||
===============
|
||||
Updating Agents (send & alter)
|
||||
==============================
|
||||
|
||||
You update an Agent by sending a function that transforms the current value or
|
||||
by sending just a new value. The Agent will apply the new value or function
|
||||
|
|
@ -75,37 +76,22 @@ in order.
|
|||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#send-off
|
||||
|
||||
All ``send`` methods also have a corresponding ``alter`` method that returns a ``Future``.
|
||||
See :ref:`futures-scala` for more information on ``Futures``.
|
||||
|
||||
Reading an Agent's value
|
||||
========================
|
||||
|
||||
Agents can be dereferenced (you can get an Agent's value) by invoking the Agent
|
||||
with parentheses like this:
|
||||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#read-apply
|
||||
|
||||
Or by using the get method:
|
||||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#read-get
|
||||
|
||||
Reading an Agent's current value does not involve any message passing and
|
||||
happens immediately. So while updates to an Agent are asynchronous, reading the
|
||||
state of an Agent is synchronous.
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#alter
|
||||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#alter-off
|
||||
|
||||
Awaiting an Agent's value
|
||||
=========================
|
||||
|
||||
It is also possible to read the value after all currently queued sends have
|
||||
completed. You can do this with ``await``:
|
||||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#read-await
|
||||
|
||||
You can also get a ``Future`` to this value, that will be completed after the
|
||||
You can also get a ``Future`` to the Agents value, that will be completed after the
|
||||
currently queued updates have completed:
|
||||
|
||||
.. includecode:: code/docs/agent/AgentDocSpec.scala#read-future
|
||||
|
||||
See :ref:`futures-scala` for more information on ``Futures``.
|
||||
|
||||
Transactional Agents
|
||||
====================
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.actor
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.actor
|
||||
|
||||
import language.postfixOps
|
||||
|
||||
import akka.testkit.{ AkkaSpec ⇒ MyFavoriteTestFrameWorkPlusAkkaTestKit }
|
||||
import akka.util.ByteString
|
||||
|
||||
//#test-code
|
||||
import akka.actor.Props
|
||||
import scala.collection.immutable
|
||||
|
|
@ -129,8 +131,7 @@ class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
|
|||
|
||||
//#transform-syntax
|
||||
when(SomeState)(transform {
|
||||
case Event(bytes: Array[Byte], read) ⇒ stay using (read + bytes.length)
|
||||
case Event(bytes: List[Byte], read) ⇒ stay using (read + bytes.size)
|
||||
case Event(bytes: ByteString, read) ⇒ stay using (read + bytes.length)
|
||||
} using {
|
||||
case s @ FSM.State(state, read, timeout, stopReason, replies) if read > 1000 ⇒
|
||||
goto(Processing)
|
||||
|
|
@ -144,8 +145,7 @@ class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
|
|||
}
|
||||
|
||||
when(SomeState)(transform {
|
||||
case Event(bytes: Array[Byte], read) ⇒ stay using (read + bytes.length)
|
||||
case Event(bytes: List[Byte], read) ⇒ stay using (read + bytes.size)
|
||||
case Event(bytes: ByteString, read) ⇒ stay using (read + bytes.length)
|
||||
} using processingTrigger)
|
||||
//#alt-transform-syntax
|
||||
|
||||
|
|
@ -211,7 +211,7 @@ class FSMDocSpec extends MyFavoriteTestFrameWorkPlusAkkaTestKit {
|
|||
expectMsg(Batch(immutable.Seq(45)))
|
||||
}
|
||||
|
||||
"batch not if uninitialized" in {
|
||||
"not batch if uninitialized" in {
|
||||
val buncher = system.actorOf(Props(new Buncher))
|
||||
buncher ! Queue(42)
|
||||
expectNoMsg
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.actor
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.actor
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.actor
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ class SchedulerDocSpec extends AkkaSpec(Map("akka.loglevel" -> "INFO")) {
|
|||
expectMsg(1 second, "foo")
|
||||
|
||||
//#schedule-one-off-thunk
|
||||
//Schedules a function to be executed (send the current time) to the testActor after 50ms
|
||||
//Schedules a function to be executed (send a message to the testActor) after 50ms
|
||||
system.scheduler.scheduleOnce(50 milliseconds) {
|
||||
testActor ! System.currentTimeMillis
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.actor
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.actor
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.agent
|
||||
|
||||
|
|
@ -7,127 +7,98 @@ import language.postfixOps
|
|||
|
||||
import akka.agent.Agent
|
||||
import scala.concurrent.duration._
|
||||
import akka.util.Timeout
|
||||
import scala.concurrent.{ Await, ExecutionContext }
|
||||
import akka.testkit._
|
||||
import scala.concurrent.Future
|
||||
|
||||
class AgentDocSpec extends AkkaSpec {
|
||||
|
||||
"create and close" in {
|
||||
"create" in {
|
||||
//#create
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import akka.agent.Agent
|
||||
|
||||
val agent = Agent(5)
|
||||
//#create
|
||||
|
||||
//#close
|
||||
agent.close()
|
||||
//#close
|
||||
}
|
||||
|
||||
"create with implicit system" in {
|
||||
//#create-implicit-system
|
||||
import akka.actor.ActorSystem
|
||||
import akka.agent.Agent
|
||||
"read value" in {
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
val agent = Agent(0)
|
||||
|
||||
implicit val system = ActorSystem("app")
|
||||
{
|
||||
//#read-apply
|
||||
val result = agent()
|
||||
//#read-apply
|
||||
result must be === 0
|
||||
}
|
||||
{
|
||||
//#read-get
|
||||
val result = agent.get
|
||||
//#read-get
|
||||
result must be === 0
|
||||
}
|
||||
|
||||
val agent = Agent(5)
|
||||
//#create-implicit-system
|
||||
|
||||
agent.close()
|
||||
system.shutdown()
|
||||
}
|
||||
|
||||
"create with explicit system" in {
|
||||
//#create-explicit-system
|
||||
import akka.actor.ActorSystem
|
||||
import akka.agent.Agent
|
||||
|
||||
val system = ActorSystem("app")
|
||||
|
||||
val agent = Agent(5)(system)
|
||||
//#create-explicit-system
|
||||
|
||||
agent.close()
|
||||
system.shutdown()
|
||||
{
|
||||
//#read-future
|
||||
val future = agent.future
|
||||
//#read-future
|
||||
Await.result(future, 5 seconds) must be === 0
|
||||
}
|
||||
}
|
||||
|
||||
"send and sendOff" in {
|
||||
val agent = Agent(0)
|
||||
import system.dispatcher
|
||||
val agent = Agent(0)(ExecutionContext.global)
|
||||
//#send
|
||||
// send a value
|
||||
// send a value, enqueues this change
|
||||
// of the value of the Agent
|
||||
agent send 7
|
||||
|
||||
// send a function
|
||||
// send a function, enqueues this change
|
||||
// to the value of the Agent
|
||||
agent send (_ + 1)
|
||||
agent send (_ * 2)
|
||||
//#send
|
||||
|
||||
def longRunningOrBlockingFunction = (i: Int) ⇒ i * 1
|
||||
|
||||
def longRunningOrBlockingFunction = (i: Int) ⇒ i * 1 // Just for the example code
|
||||
def someExecutionContext() = scala.concurrent.ExecutionContext.Implicits.global // Just for the example code
|
||||
//#send-off
|
||||
// the ExecutionContext you want to run the function on
|
||||
implicit val ec = someExecutionContext()
|
||||
// sendOff a function
|
||||
agent sendOff (longRunningOrBlockingFunction)
|
||||
agent sendOff longRunningOrBlockingFunction
|
||||
//#send-off
|
||||
|
||||
val result = agent.await(Timeout(5 seconds))
|
||||
result must be === 16
|
||||
Await.result(agent.future, 5 seconds) must be === 16
|
||||
}
|
||||
|
||||
"read with apply" in {
|
||||
val agent = Agent(0)
|
||||
"alter and alterOff" in {
|
||||
val agent = Agent(0)(ExecutionContext.global)
|
||||
//#alter
|
||||
// alter a value
|
||||
val f1: Future[Int] = agent alter 7
|
||||
|
||||
//#read-apply
|
||||
val result = agent()
|
||||
//#read-apply
|
||||
// alter a function
|
||||
val f2: Future[Int] = agent alter (_ + 1)
|
||||
val f3: Future[Int] = agent alter (_ * 2)
|
||||
//#alter
|
||||
|
||||
result must be === 0
|
||||
}
|
||||
def longRunningOrBlockingFunction = (i: Int) ⇒ i * 1 // Just for the example code
|
||||
def someExecutionContext() = ExecutionContext.global // Just for the example code
|
||||
|
||||
"read with get" in {
|
||||
val agent = Agent(0)
|
||||
//#alter-off
|
||||
// the ExecutionContext you want to run the function on
|
||||
implicit val ec = someExecutionContext()
|
||||
// alterOff a function
|
||||
val f4: Future[Int] = agent alterOff longRunningOrBlockingFunction
|
||||
//#alter-off
|
||||
|
||||
//#read-get
|
||||
val result = agent.get
|
||||
//#read-get
|
||||
|
||||
result must be === 0
|
||||
}
|
||||
|
||||
"read with await" in {
|
||||
val agent = Agent(0)
|
||||
|
||||
//#read-await
|
||||
import scala.concurrent.duration._
|
||||
import akka.util.Timeout
|
||||
|
||||
implicit val timeout = Timeout(5 seconds)
|
||||
val result = agent.await
|
||||
//#read-await
|
||||
|
||||
result must be === 0
|
||||
}
|
||||
|
||||
"read with future" in {
|
||||
val agent = Agent(0)
|
||||
|
||||
//#read-future
|
||||
import scala.concurrent.Await
|
||||
|
||||
implicit val timeout = Timeout(5 seconds)
|
||||
val future = agent.future
|
||||
val result = Await.result(future, timeout.duration)
|
||||
//#read-future
|
||||
|
||||
result must be === 0
|
||||
Await.result(f4, 5 seconds) must be === 16
|
||||
}
|
||||
|
||||
"transfer example" in {
|
||||
//#transfer-example
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
import akka.agent.Agent
|
||||
import scala.concurrent.duration._
|
||||
import akka.util.Timeout
|
||||
import scala.concurrent.stm._
|
||||
|
||||
def transfer(from: Agent[Int], to: Agent[Int], amount: Int): Boolean = {
|
||||
|
|
@ -145,25 +116,25 @@ class AgentDocSpec extends AkkaSpec {
|
|||
val to = Agent(20)
|
||||
val ok = transfer(from, to, 50)
|
||||
|
||||
implicit val timeout = Timeout(5 seconds)
|
||||
val fromValue = from.await // -> 50
|
||||
val toValue = to.await // -> 70
|
||||
val fromValue = from.future // -> 50
|
||||
val toValue = to.future // -> 70
|
||||
//#transfer-example
|
||||
|
||||
fromValue must be === 50
|
||||
toValue must be === 70
|
||||
Await.result(fromValue, 5 seconds) must be === 50
|
||||
Await.result(toValue, 5 seconds) must be === 70
|
||||
ok must be === true
|
||||
}
|
||||
|
||||
"monadic example" in {
|
||||
def println(a: Any) = ()
|
||||
//#monadic-example
|
||||
import scala.concurrent.ExecutionContext.Implicits.global
|
||||
val agent1 = Agent(3)
|
||||
val agent2 = Agent(5)
|
||||
|
||||
// uses foreach
|
||||
var result = 0
|
||||
for (value ← agent1) {
|
||||
result = value + 1
|
||||
}
|
||||
for (value ← agent1)
|
||||
println(value)
|
||||
|
||||
// uses map
|
||||
val agent3 = for (value ← agent1) yield value + 1
|
||||
|
|
@ -178,15 +149,8 @@ class AgentDocSpec extends AkkaSpec {
|
|||
} yield value1 + value2
|
||||
//#monadic-example
|
||||
|
||||
result must be === 4
|
||||
agent3() must be === 4
|
||||
agent4() must be === 4
|
||||
agent5() must be === 8
|
||||
|
||||
agent1.close()
|
||||
agent2.close()
|
||||
agent3.close()
|
||||
agent4.close()
|
||||
agent5.close()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package docs.camel
|
||||
|
|
@ -70,4 +70,4 @@ object Consumers {
|
|||
}
|
||||
//#Consumer4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package docs.camel
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.dataflow
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.dispatcher
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.event
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.extension
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.extension
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.future
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.io
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.io
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package docs.pattern
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package docs.pattern
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.remoting
|
||||
|
||||
|
|
@ -20,15 +20,15 @@ object RemoteDeploymentDocSpec {
|
|||
|
||||
class RemoteDeploymentDocSpec extends AkkaSpec("""
|
||||
akka.actor.provider = "akka.remote.RemoteActorRefProvider"
|
||||
akka.remoting.transports.tcp.port = 0
|
||||
akka.remote.netty.tcp.port = 0
|
||||
""") with ImplicitSender {
|
||||
|
||||
import RemoteDeploymentDocSpec._
|
||||
|
||||
val other = ActorSystem("remote", system.settings.config)
|
||||
val address = other.asInstanceOf[ExtendedActorSystem].provider.getExternalAddressFor(Address("tcp.akka", "s", "host", 1)).get
|
||||
val address = other.asInstanceOf[ExtendedActorSystem].provider.getExternalAddressFor(Address("akka.tcp", "s", "host", 1)).get
|
||||
|
||||
override def atTermination() { other.shutdown() }
|
||||
override def afterTermination() { other.shutdown() }
|
||||
|
||||
"demonstrate programmatic deployment" in {
|
||||
//#deploy
|
||||
|
|
@ -42,8 +42,8 @@ class RemoteDeploymentDocSpec extends AkkaSpec("""
|
|||
|
||||
"demonstrate address extractor" in {
|
||||
//#make-address
|
||||
val one = AddressFromURIString("tcp.akka://sys@host:1234")
|
||||
val two = Address("tcp.akka", "sys", "host", 1234) // this gives the same
|
||||
val one = AddressFromURIString("akka.tcp://sys@host:1234")
|
||||
val two = Address("akka.tcp", "sys", "host", 1234) // this gives the same
|
||||
//#make-address
|
||||
one must be === two
|
||||
}
|
||||
|
|
@ -56,4 +56,4 @@ class RemoteDeploymentDocSpec extends AkkaSpec("""
|
|||
//#sample-actor
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.routing
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.routing
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.routing
|
||||
|
||||
|
|
@ -91,4 +91,4 @@ class ParentActor extends Actor {
|
|||
}
|
||||
}
|
||||
|
||||
//#parentActor
|
||||
//#parentActor
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.routing
|
||||
|
||||
|
|
@ -155,4 +155,4 @@ class RouterWithConfigDocSpec extends AkkaSpec(RouterWithConfigDocSpec.config) w
|
|||
receiveN(10)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.routing
|
||||
|
||||
|
|
@ -49,4 +49,4 @@ object RouterWithConfigExample extends App {
|
|||
"router2")
|
||||
//#configurableRoutingWithResizer
|
||||
1 to 10 foreach { i ⇒ router2 ! Message(i) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.routing
|
||||
|
||||
|
|
@ -50,4 +50,4 @@ object RoutingProgrammaticallyExample extends App {
|
|||
RemoteRouterConfig(RoundRobinRouter(5), addresses)))
|
||||
//#remoteRoutees
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package docs.serialization {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.testkit
|
||||
|
||||
|
|
@ -44,4 +44,4 @@ class MySpec(_system: ActorSystem) extends TestKit(_system) with ImplicitSender
|
|||
|
||||
}
|
||||
}
|
||||
//#plain-spec
|
||||
//#plain-spec
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.testkit
|
||||
|
||||
|
|
@ -157,4 +157,4 @@ object TestKitUsageSpec {
|
|||
}
|
||||
}
|
||||
}
|
||||
//#testkit-usage
|
||||
//#testkit-usage
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.testkit
|
||||
|
||||
|
|
@ -206,6 +206,16 @@ class TestkitDocSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
|
|||
//#test-special-probe
|
||||
}
|
||||
|
||||
"demonstrate probe watch" in {
|
||||
import akka.testkit.TestProbe
|
||||
val target = system.actorFor("/buh")
|
||||
//#test-probe-watch
|
||||
val probe = TestProbe()
|
||||
probe watch target
|
||||
probe.expectMsgType[Terminated].actor must be(target)
|
||||
//#test-probe-watch
|
||||
}
|
||||
|
||||
"demonstrate probe reply" in {
|
||||
import akka.testkit.TestProbe
|
||||
import scala.concurrent.duration._
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package docs.transactor
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.zeromq
|
||||
|
||||
|
|
|
|||
|
|
@ -129,6 +129,11 @@ Note that ``thread-pool-executor`` configuration as per the above ``my-thread-po
|
|||
NOT applicable. This is because every actor will have its own thread pool when using ``PinnedDispatcher``,
|
||||
and that pool will have only one thread.
|
||||
|
||||
Note that it's not guaranteed that the *same* thread is used over time, since the core pool timeout
|
||||
is used for ``PinnedDispatcher`` to keep resource usage down in case of idle actors. To use the same
|
||||
thread all the time you need to add ``thread-pool-executor.allow-core-timeout=off`` to the
|
||||
configuration of the ``PinnedDispatcher``.
|
||||
|
||||
Mailboxes
|
||||
---------
|
||||
|
||||
|
|
|
|||
|
|
@ -5,22 +5,23 @@
|
|||
Scheduler (Scala)
|
||||
###################
|
||||
|
||||
Sometimes the need for making things happen in the future arises, and where do you go look then?
|
||||
Look no further than ``ActorSystem``! There you find the :meth:`scheduler` method that returns an instance
|
||||
of akka.actor.Scheduler, this instance is unique per ActorSystem and is used internally for scheduling things
|
||||
to happen at specific points in time. Please note that the scheduled tasks are executed by the default
|
||||
``MessageDispatcher`` of the ``ActorSystem``.
|
||||
Sometimes the need for making things happen in the future arises, and where do
|
||||
you go look then? Look no further than ``ActorSystem``! There you find the
|
||||
:meth:`scheduler` method that returns an instance of
|
||||
:class:`akka.actor.Scheduler`, this instance is unique per ActorSystem and is
|
||||
used internally for scheduling things to happen at specific points in time.
|
||||
|
||||
You can schedule sending of messages to actors and execution of tasks (functions or Runnable).
|
||||
You will get a ``Cancellable`` back that you can call :meth:`cancel` on to cancel the execution of the
|
||||
scheduled operation.
|
||||
You can schedule sending of messages to actors and execution of tasks
|
||||
(functions or Runnable). You will get a ``Cancellable`` back that you can call
|
||||
:meth:`cancel` on to cancel the execution of the scheduled operation.
|
||||
|
||||
.. warning::
|
||||
|
||||
The default implementation of ``Scheduler`` used by Akka is based on the Netty ``HashedWheelTimer``.
|
||||
It does not execute tasks at the exact time, but on every tick, it will run everything that is overdue.
|
||||
The accuracy of the default Scheduler can be modified by the "ticks-per-wheel" and "tick-duration" configuration
|
||||
properties. For more information, see: `HashedWheelTimers <http://www.cse.wustl.edu/~cdgill/courses/cs6874/TimingWheels.ppt>`_.
|
||||
The default implementation of ``Scheduler`` used by Akka is based on job
|
||||
buckets which are emptied according to a fixed schedule. It does not
|
||||
execute tasks at the exact time, but on every tick, it will run everything
|
||||
that is (over)due. The accuracy of the default Scheduler can be modified
|
||||
by the ``akka.scheduler.tick-duration`` configuration property.
|
||||
|
||||
Some examples
|
||||
-------------
|
||||
|
|
@ -44,16 +45,26 @@ From ``akka.actor.ActorSystem``
|
|||
The Scheduler interface
|
||||
-----------------------
|
||||
|
||||
The actual scheduler implementation is loaded reflectively upon
|
||||
:class:`ActorSystem` start-up, which means that it is possible to provide a
|
||||
different one using the ``akka.scheduler.implementation`` configuration
|
||||
property. The referenced class must implement the following interface:
|
||||
|
||||
.. includecode:: ../../../akka-actor/src/main/scala/akka/actor/Scheduler.scala
|
||||
:include: scheduler
|
||||
|
||||
The Cancellable interface
|
||||
-------------------------
|
||||
|
||||
This allows you to ``cancel`` something that has been scheduled for execution.
|
||||
Scheduling a task will result in a :class:`Cancellable` (or throw an
|
||||
:class:`IllegalStateException` if attempted after the scheduler’s shutdown).
|
||||
This allows you to cancel something that has been scheduled for execution.
|
||||
|
||||
.. warning::
|
||||
This does not abort the execution of the task, if it had already been started.
|
||||
|
||||
This does not abort the execution of the task, if it had already been
|
||||
started. Check the return value of ``cancel`` to detect whether the
|
||||
scheduled task was canceled or will (eventually) have run.
|
||||
|
||||
.. includecode:: ../../../akka-actor/src/main/scala/akka/actor/Scheduler.scala
|
||||
:include: cancellable
|
||||
|
|
|
|||
|
|
@ -446,6 +446,23 @@ facilities with your own checks and choosing an intuitive name for it. In real
|
|||
life your code will probably be a bit more complicated than the example given
|
||||
above; just use the power!
|
||||
|
||||
.. warning::
|
||||
|
||||
Any message send from a ``TestProbe`` to another actor which runs on the
|
||||
CallingThreadDispatcher runs the risk of dead-lock, if that other actor might
|
||||
also send to this probe. The implementation of :meth:`TestProbe.watch` and
|
||||
:meth:`TestProbe.unwatch` will also send a message to the watchee, which
|
||||
means that it is dangerous to try watching e.g. :class:`TestActorRef` from a
|
||||
:meth:`TestProbe`.
|
||||
|
||||
Watching Other Actors from Probes
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A :class:`TestKit` can register itself for DeathWatch of any other actor:
|
||||
|
||||
.. includecode:: code/docs/testkit/TestkitDocSpec.scala
|
||||
:include: test-probe-watch
|
||||
|
||||
Replying to Messages Received by Probes
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -597,6 +614,28 @@ production.
|
|||
scenarios, but keep in mind that it has may give false negatives as well as
|
||||
false positives.
|
||||
|
||||
Thread Interruptions
|
||||
--------------------
|
||||
|
||||
If the CallingThreadDispatcher sees that the current thread has its
|
||||
``isInterrupted()`` flag set when message processing returns, it will throw an
|
||||
:class:`InterruptedException` after finishing all its processing (i.e. all
|
||||
messages which need processing as described above are processed before this
|
||||
happens). As :meth:`tell` cannot throw exceptions due to its contract, this
|
||||
exception will then be caught and logged, and the thread’s interrupted status
|
||||
will be set again.
|
||||
|
||||
If during message processing an :class:`InterruptedException` is thrown then it
|
||||
will be caught inside the CallingThreadDispatcher’s message handling loop, the
|
||||
thread’s interrupted flag will be set and processing continues normally.
|
||||
|
||||
.. note::
|
||||
|
||||
The summary of these two paragraphs is that if the current thread is
|
||||
interrupted while doing work under the CallingThreadDispatcher, then that
|
||||
will result in the ``isInterrupted`` flag to be ``true`` when the message
|
||||
send returns and no :class:`InterruptedException` will be thrown.
|
||||
|
||||
Benefits
|
||||
--------
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue