Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' into wip-2006-binary-compat-√

  • Loading branch information...
commit 4fe863a58c43579ed9c56e2f6556bd43f82ab988 2 parents 6d43012 + 2e248e4
@viktorklang viktorklang authored
View
4 .gitignore
@@ -50,8 +50,6 @@ multiverse.log
.*.swp
akka-docs/_build/
*.pyc
-akka-tutorials/akka-tutorial-first/project/boot/
-akka-tutorials/akka-tutorial-first/project/plugins/project/
akka-docs/exts/
_akka_cluster/
Makefile
@@ -65,4 +63,4 @@ worker*.log
mongoDB/
redis/
beanstalk/
-.scalastyle
+.scalastyle
View
29 akka-docs/scala/dataflow.rst
@@ -6,7 +6,7 @@ Description
Akka implements `Oz-style dataflow concurrency <http://www.mozart-oz.org/documentation/tutorial/node8.html#chapter.concurrency>`_ by using a special API for :ref:`futures-scala` that allows single assignment variables and multiple lightweight (event-based) processes/threads.
-Dataflow concurrency is deterministic. This means that it will always behave the same. If you run it once and it yields output 5 then it will do that **every time**, run it 10 million times, same result. If it on the other hand deadlocks the first time you run it, then it will deadlock **every single time** you run it. Also, there is **no difference** between sequential code and concurrent code. These properties makes it very easy to reason about concurrency. The limitation is that the code needs to be side-effect free, e.g. deterministic. You can't use exceptions, time, random etc., but need to treat the part of your program that uses dataflow concurrency as a pure function with input and output.
+Dataflow Concurrency has its origin in logic programming and is declarative and fully deterministic. This means that it will always behave the same. If you run it once and it yields output ``5`` then it will do that **every time**, run it 10 million times, same result. If it on the other hand deadlocks the first time you run it, then it will deadlock **every single time** you run it. Also, there is **no difference** between sequential code and concurrent code. These properties makes it very easy to reason about concurrency. The limitation is that the code needs to be side-effect free, e.g. deterministic. You can't use exceptions, time, random etc., but need to treat the part of your program that uses dataflow concurrency as a pure function with input and output.
The best way to learn how to program with dataflow variables is to read the fantastic book `Concepts, Techniques, and Models of Computer Programming <http://www.info.ucl.ac.be/%7Epvr/book.html>`_. By Peter Van Roy and Seif Haridi.
@@ -26,6 +26,15 @@ Scala's Delimited Continuations plugin is required to use the Dataflow API. To e
libraryDependencies <+= scalaVersion { v => compilerPlugin("org.scala-lang.plugins" % "continuations" % <scalaVersion>) },
scalacOptions += "-P:continuations:enable",
+To use the DataFlow library you have to provide an implicit ExecutionContext, here is an example:
+
+.. code-block:: scala
+
+ import akka.dispatch._
+ import java.util.concurrent.Executors
+
+ implicit val ec = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(..))
+
Dataflow Variables
------------------
@@ -65,7 +74,7 @@ Dataflow is implemented in Akka using Scala's Delimited Continuations. To use th
.. code-block:: scala
import Future.flow
- implicit val dispatcher = ...
+ implicit val executionContext = ...
val a = Future( ... )
val b = Future( ... )
@@ -82,7 +91,7 @@ The ``flow`` method also returns a ``Future`` for the result of the contained ex
.. code-block:: scala
import Future.flow
- implicit val dispatcher = ...
+ implicit val executionContext = ...
val a = Future( ... )
val b = Future( ... )
@@ -116,7 +125,7 @@ To run these examples:
scala>
-2. Paste the examples (below) into the Scala REPL.
+2. Paste the examples (below) into the Scala REPL. Paste in each of the ``flow`` blocks at a time to see data flow in action.
Note: Do not try to run the Oz version, it is only there for reference.
3. Have fun.
@@ -144,7 +153,9 @@ Example in Akka:
import akka.dispatch._
import Future.flow
- implicit val dispatcher = ...
+ import java.util.concurrent.Executors
+
+ implicit val ec = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4))
val x, y, z = Promise[Int]()
@@ -189,7 +200,9 @@ Example in Akka:
import akka.dispatch._
import Future.flow
- implicit val dispatcher = ...
+ import java.util.concurrent.Executors
+
+ implicit val ec = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4))
def ints(n: Int, max: Int): List[Int] = {
if (n == max) Nil
@@ -218,7 +231,9 @@ Example in Akka:
import akka.dispatch._
import Future.flow
- implicit val dispatcher = ...
+ import java.util.concurrent.Executors
+
+ implicit val ec = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4))
// create four 'Int' data flow variables
val x, y, z, v = Promise[Int]()
View
7 akka-tutorials/akka-tutorial-first/README
@@ -1,7 +0,0 @@
-================
- First Tutorial
-================
-
-This is the source code for the first tutorial.
-
-See the Akka Documentation for information about this tutorial.
View
43 akka-tutorials/akka-tutorial-first/pom.xml
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <name>akka-tutorial-first-java</name>
- <groupId>akka.tutorial.first.java</groupId>
- <artifactId>akka-tutorial-first-java</artifactId>
- <packaging>jar</packaging>
- <version>2.1-SNAPSHOT</version>
- <url>http://akka.io</url>
-
- <dependencies>
- <dependency>
- <groupId>com.typesafe.akka</groupId>
- <artifactId>akka-actor</artifactId>
- <version>2.1-SNAPSHOT</version>
- </dependency>
- </dependencies>
-
- <repositories>
- <repository>
- <id>Akka</id>
- <name>Akka Maven2 Repository</name>
- <url>http://akka.io/repository/</url>
- </repository>
- </repositories>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>2.3.2</version>
- <configuration>
- <source>1.6</source>
- <target>1.6</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
View
22 akka-tutorials/akka-tutorial-first/project/TutorialBuild.scala
@@ -1,22 +0,0 @@
-import sbt._
-import Keys._
-
-object TutorialBuild extends Build {
- lazy val buildSettings = Seq(
- organization := "com.typesafe.akka",
- version := "2.1-SNAPSHOT",
- scalaVersion := "2.9.1"
- )
-
- lazy val akka = Project(
- id = "akka-tutorial-first",
- base = file("."),
- settings = Defaults.defaultSettings ++ Seq(
- libraryDependencies ++= Seq(
- "com.typesafe.akka" % "akka-actor" % "2.1-SNAPSHOT",
- "junit" % "junit" % "4.5" % "test",
- "org.scalatest" % "scalatest_2.9.0" % "1.6.1" % "test",
- "com.typesafe.akka" % "akka-testkit" % "2.1-SNAPSHOT" % "test")
- )
- )
-}
View
1  akka-tutorials/akka-tutorial-first/project/build.properties
@@ -1 +0,0 @@
-sbt.version=0.11.0
View
197 akka-tutorials/akka-tutorial-first/src/main/java/akka/tutorial/first/java/Pi.java
@@ -1,197 +0,0 @@
-/**
- * Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
- */
-
-package akka.tutorial.first.java;
-
-//#imports
-
-import akka.actor.ActorRef;
-import akka.actor.ActorSystem;
-import akka.actor.Props;
-import akka.actor.UntypedActor;
-import akka.actor.UntypedActorFactory;
-import akka.routing.RoundRobinRouter;
-import akka.util.Duration;
-import java.util.concurrent.TimeUnit;
-
-//#imports
-
-//#app
-public class Pi {
-
- public static void main(String[] args) {
- Pi pi = new Pi();
- pi.calculate(4, 10000, 10000);
- }
-
- //#actors-and-messages
- //#messages
- static class Calculate {
- }
-
- static class Work {
- private final int start;
- private final int nrOfElements;
-
- public Work(int start, int nrOfElements) {
- this.start = start;
- this.nrOfElements = nrOfElements;
- }
-
- public int getStart() {
- return start;
- }
-
- public int getNrOfElements() {
- return nrOfElements;
- }
- }
-
- static class Result {
- private final double value;
-
- public Result(double value) {
- this.value = value;
- }
-
- public double getValue() {
- return value;
- }
- }
-
- static class PiApproximation {
- private final double pi;
- private final Duration duration;
-
- public PiApproximation(double pi, Duration duration) {
- this.pi = pi;
- this.duration = duration;
- }
-
- public double getPi() {
- return pi;
- }
-
- public Duration getDuration() {
- return duration;
- }
- }
-
- //#messages
-
- //#worker
- public static class Worker extends UntypedActor {
-
- //#calculatePiFor
- private double calculatePiFor(int start, int nrOfElements) {
- double acc = 0.0;
- for (int i = start * nrOfElements; i <= ((start + 1) * nrOfElements - 1); i++) {
- acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1);
- }
- return acc;
- }
-
- //#calculatePiFor
-
- public void onReceive(Object message) {
- if (message instanceof Work) {
- Work work = (Work) message;
- double result = calculatePiFor(work.getStart(), work.getNrOfElements());
- getSender().tell(new Result(result), getSelf());
- } else {
- unhandled(message);
- }
- }
- }
-
- //#worker
-
- //#master
- public static class Master extends UntypedActor {
- private final int nrOfMessages;
- private final int nrOfElements;
-
- private double pi;
- private int nrOfResults;
- private final long start = System.currentTimeMillis();
-
- private final ActorRef listener;
- private final ActorRef workerRouter;
-
- public Master(final int nrOfWorkers, int nrOfMessages, int nrOfElements, ActorRef listener) {
- this.nrOfMessages = nrOfMessages;
- this.nrOfElements = nrOfElements;
- this.listener = listener;
-
- //#create-router
- workerRouter = this.getContext().actorOf(new Props(Worker.class).withRouter(new RoundRobinRouter(nrOfWorkers)),
- "workerRouter");
- //#create-router
- }
-
- //#master-receive
- public void onReceive(Object message) {
- //#handle-messages
- if (message instanceof Calculate) {
- for (int start = 0; start < nrOfMessages; start++) {
- workerRouter.tell(new Work(start, nrOfElements), getSelf());
- }
- } else if (message instanceof Result) {
- Result result = (Result) message;
- pi += result.getValue();
- nrOfResults += 1;
- if (nrOfResults == nrOfMessages) {
- // Send the result to the listener
- Duration duration = Duration.create(System.currentTimeMillis() - start, TimeUnit.MILLISECONDS);
- listener.tell(new PiApproximation(pi, duration), getSelf());
- // Stops this actor and all its supervised children
- getContext().stop(getSelf());
- }
- } else {
- unhandled(message);
- }
- //#handle-messages
- }
- //#master-receive
- }
-
- //#master
-
- //#result-listener
- public static class Listener extends UntypedActor {
- public void onReceive(Object message) {
- if (message instanceof PiApproximation) {
- PiApproximation approximation = (PiApproximation) message;
- System.out.println(String.format("\n\tPi approximation: \t\t%s\n\tCalculation time: \t%s",
- approximation.getPi(), approximation.getDuration()));
- getContext().system().shutdown();
- } else {
- unhandled(message);
- }
- }
- }
-
- //#result-listener
- //#actors-and-messages
-
- public void calculate(final int nrOfWorkers, final int nrOfElements, final int nrOfMessages) {
- // Create an Akka system
- ActorSystem system = ActorSystem.create("PiSystem");
-
- // create the result listener, which will print the result and shutdown the system
- final ActorRef listener = system.actorOf(new Props(Listener.class), "listener");
-
- // create the master
- ActorRef master = system.actorOf(new Props(new UntypedActorFactory() {
- public UntypedActor create() {
- return new Master(nrOfWorkers, nrOfMessages, nrOfElements, listener);
- }
- }), "master");
-
- // start the calculation
- master.tell(new Calculate());
-
- }
-}
-//#app
View
7 akka-tutorials/akka-tutorial-first/src/main/resources/application.conf
@@ -1,7 +0,0 @@
-akka.actor.deployment {
- /master/workerRouter {
- # Uncomment the following two lines to change the calculation to use 10 workers instead of 4:
- #router = round-robin
- #nr-of-instances = 10
- }
-}
View
110 akka-tutorials/akka-tutorial-first/src/main/scala/akka/tutorial/first/scala/Pi.scala
@@ -1,110 +0,0 @@
-/**
- * Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
- */
-package akka.tutorial.first.scala
-
-//#imports
-import akka.actor._
-import akka.routing.RoundRobinRouter
-import akka.util.Duration
-import akka.util.duration._
-//#imports
-
-//#app
-object Pi extends App {
-
- calculate(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000)
-
- //#actors-and-messages
- //#messages
- sealed trait PiMessage
- case object Calculate extends PiMessage
- case class Work(start: Int, nrOfElements: Int) extends PiMessage
- case class Result(value: Double) extends PiMessage
- case class PiApproximation(pi: Double, duration: Duration)
- //#messages
-
- //#worker
- class Worker extends Actor {
-
- //#calculatePiFor
- def calculatePiFor(start: Int, nrOfElements: Int): Double = {
- var acc = 0.0
- for (i start until (start + nrOfElements))
- acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1)
- acc
- }
- //#calculatePiFor
-
- def receive = {
- case Work(start, nrOfElements)
- sender ! Result(calculatePiFor(start, nrOfElements)) // perform the work
- }
- }
- //#worker
-
- //#master
- class Master(nrOfWorkers: Int, nrOfMessages: Int, nrOfElements: Int, listener: ActorRef)
- extends Actor {
-
- var pi: Double = _
- var nrOfResults: Int = _
- val start: Long = System.currentTimeMillis()
-
- //#create-router
- val workerRouter = context.actorOf(
- Props[Worker].withRouter(RoundRobinRouter(nrOfWorkers)), name = "workerRouter")
- //#create-router
-
- //#master-receive
- def receive = {
- //#handle-messages
- case Calculate
- for (i 0 until nrOfMessages) workerRouter ! Work(i * nrOfElements, nrOfElements)
- case Result(value)
- pi += value
- nrOfResults += 1
- if (nrOfResults == nrOfMessages) {
- // Send the result to the listener
- listener ! PiApproximation(pi, duration = (System.currentTimeMillis() - start).millis)
- // Stops this actor and all its supervised children
- context.stop(self)
- }
- //#handle-messages
- }
- //#master-receive
-
- }
- //#master
-
- //#result-listener
- class Listener extends Actor {
- def receive = {
- case PiApproximation(pi, duration)
- println("\n\tPi approximation: \t\t%s\n\tCalculation time: \t%s"
- .format(pi, duration))
- context.system.shutdown()
- }
- }
- //#result-listener
-
- //#actors-and-messages
-
- def calculate(nrOfWorkers: Int, nrOfElements: Int, nrOfMessages: Int) {
- // Create an Akka system
- val system = ActorSystem("PiSystem")
-
- // create the result listener, which will print the result and shutdown the system
- val listener = system.actorOf(Props[Listener], name = "listener")
-
- // create the master
- val master = system.actorOf(Props(new Master(
- nrOfWorkers, nrOfMessages, nrOfElements, listener)),
- name = "master")
-
- // start the calculation
- master ! Calculate
-
- }
-}
-//#app
View
31 akka-tutorials/akka-tutorial-first/src/test/scala/WorkerSpec.scala
@@ -1,31 +0,0 @@
-/**
- * Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
- */
-package akka.tutorial.first.scala
-
-import org.junit.runner.RunWith
-import org.scalatest.matchers.MustMatchers
-import org.scalatest.BeforeAndAfterAll
-import org.scalatest.WordSpec
-import akka.testkit.TestActorRef
-import akka.tutorial.first.scala.Pi.Worker
-import akka.actor.ActorSystem
-
-@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner])
-class WorkerSpec extends WordSpec with MustMatchers with BeforeAndAfterAll {
-
- implicit val system = ActorSystem()
-
- override def afterAll {
- system.shutdown()
- }
-
- "Worker" must {
- "calculate pi correctly" in {
- val testActor = TestActorRef[Worker]
- val actor = testActor.underlyingActor
- actor.calculatePiFor(0, 0) must equal(0.0)
- actor.calculatePiFor(1, 1) must be(-1.3333333333333333 plusOrMinus 0.0000000001)
- }
- }
-}
Please sign in to comment.
Something went wrong with that request. Please try again.