├── throughputs.ods
├── enter-talk-and-leave.png
├── simply-sending-messages.png
├── enter-while-others-are-talking.png
├── Vagrantfiles
└── intellij
│ ├── mavenVersion.xml
│ ├── git.xml
│ ├── project.default.xml
│ └── jdk.table.xml
├── hack.sh
├── src
├── main
│ └── java
│ │ └── net
│ │ └── bourgau
│ │ └── philippe
│ │ └── concurrency
│ │ └── kata
│ │ ├── common
│ │ ├── Output.java
│ │ ├── Client.java
│ │ ├── Implementation.java
│ │ ├── UnsafeRunnable.java
│ │ ├── ChatRoom.java
│ │ ├── Message.java
│ │ ├── SynchronizedChatRoom.java
│ │ ├── InProcessClient.java
│ │ ├── ConcurrentChatRoom.java
│ │ ├── ThreadPoolImplementation.java
│ │ ├── UncheckedThrow.java
│ │ └── InProcessChatRoom.java
│ │ ├── csp
│ │ ├── Action.java
│ │ ├── ChatRoomCoRoutine.java
│ │ ├── ClientCoRoutine.java
│ │ ├── ClientAdapter.java
│ │ ├── ChatRoomMessages.java
│ │ ├── ClientMessages.java
│ │ ├── ChatRoomAdapter.java
│ │ ├── Channel.java
│ │ └── CSP.java
│ │ ├── monothread
│ │ └── MonoThread.java
│ │ ├── unbounded
│ │ ├── sync
│ │ │ └── UnboundedSync.java
│ │ └── concurrent
│ │ │ └── UnboundedConcurrent.java
│ │ ├── bounded
│ │ ├── concurrent
│ │ │ └── BoundedConcurrent.java
│ │ └── finegrained
│ │ │ ├── BoundedFineGrained.java
│ │ │ └── FineGrainedChatRoom.java
│ │ └── actors
│ │ └── threads
│ │ ├── green
│ │ ├── ActorsGreenThreads.java
│ │ ├── Actor.java
│ │ ├── ChatRoomActor.java
│ │ └── ClientActor.java
│ │ └── real
│ │ ├── ConcurrentClient.java
│ │ └── ActorsRealThreads.java
└── test
│ └── java
│ └── net
│ └── bourgau
│ └── philippe
│ └── concurrency
│ └── kata
│ ├── NullOutput.java
│ ├── MatchingOutput.java
│ ├── DotOutput.java
│ ├── MemoryOutput.java
│ ├── CountingOutput.java
│ ├── benchmarks
│ ├── EnterTalkAndLeaveBenchmark.java
│ ├── EnterWhileTalkingBenchmark.java
│ ├── MessageSendingBenchmark.java
│ └── BenchmarkTest.java
│ ├── Implementations.java
│ └── tests
│ ├── EndToEndTest.java
│ └── ConcurrencyTest.java
├── .gitignore
├── LICENSE
├── Dockerfile
├── pom.xml
├── Vagrantfile
└── README.md
/throughputs.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philou/concurrency-kata/HEAD/throughputs.ods
--------------------------------------------------------------------------------
/enter-talk-and-leave.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philou/concurrency-kata/HEAD/enter-talk-and-leave.png
--------------------------------------------------------------------------------
/simply-sending-messages.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philou/concurrency-kata/HEAD/simply-sending-messages.png
--------------------------------------------------------------------------------
/enter-while-others-are-talking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/philou/concurrency-kata/HEAD/enter-while-others-are-talking.png
--------------------------------------------------------------------------------
/Vagrantfiles/intellij/mavenVersion.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/hack.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ssh-keygen -f "`realpath ~`/.ssh/known_hosts" -R [localhost]:2222
4 | vagrant up
5 | ssh -X -p 2222 vagrant@localhost .idea/bin/idea.sh /vagrant/pom.xml
6 |
--------------------------------------------------------------------------------
/src/main/java/net/bourgau/philippe/concurrency/kata/common/Output.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata.common;
2 |
3 | public interface Output {
4 | void write(String line);
5 | }
6 |
--------------------------------------------------------------------------------
/Vagrantfiles/intellij/git.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/java/net/bourgau/philippe/concurrency/kata/common/Client.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata.common;
2 |
3 | public interface Client extends Output {
4 | void enter() throws Exception;
5 |
6 | void announce(String message);
7 |
8 | void leave() throws Exception;
9 | }
10 |
--------------------------------------------------------------------------------
/src/test/java/net/bourgau/philippe/concurrency/kata/NullOutput.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata;
2 |
3 | import net.bourgau.philippe.concurrency.kata.common.Output;
4 |
5 | public class NullOutput implements Output {
6 | @Override
7 | public void write(String line) {
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
14 | # emacs files
15 | *~
16 |
17 | # vagrant files
18 | .vagrant
19 |
20 | # Intellij files
21 | *.iml
22 | .idea
23 |
24 | # maven files
25 | target
26 |
27 | # temp files
28 | *#
--------------------------------------------------------------------------------
/src/main/java/net/bourgau/philippe/concurrency/kata/common/Implementation.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata.common;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | public interface Implementation {
6 | ChatRoom startNewChatRoom();
7 |
8 | Client newClient(String name, ChatRoom chatRoom, Output out);
9 |
10 | void awaitOrShutdown(int count, TimeUnit timeUnit) throws InterruptedException;
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/net/bourgau/philippe/concurrency/kata/csp/Action.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata.csp;
2 |
3 | public abstract class Action {
4 |
5 | public void execute(T subject) {
6 | try {
7 | doExecute(subject);
8 |
9 | } catch (Exception e) {
10 | e.printStackTrace();
11 | }
12 | }
13 |
14 | protected abstract void doExecute(T subject) throws Exception;
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/net/bourgau/philippe/concurrency/kata/common/UnsafeRunnable.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata.common;
2 |
3 | public abstract class UnsafeRunnable implements Runnable {
4 |
5 | @Override
6 | public void run() {
7 | try {
8 | doRun();
9 |
10 | } catch (Exception e) {
11 | e.printStackTrace();
12 | }
13 | }
14 |
15 | protected abstract void doRun() throws Exception;
16 | }
--------------------------------------------------------------------------------
/src/test/java/net/bourgau/philippe/concurrency/kata/MatchingOutput.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata;
2 |
3 | public class MatchingOutput extends CountingOutput {
4 | private final String subMessage;
5 |
6 | public MatchingOutput(String subMessage) {
7 | this.subMessage = subMessage;
8 | }
9 |
10 | @Override
11 | public void write(String line) {
12 | if (line.contains(subMessage)) {
13 | super.write(line);
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/net/bourgau/philippe/concurrency/kata/common/ChatRoom.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata.common;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | public interface ChatRoom {
6 | String GOD_PREFIX = "QPHILIPPEZDFSDFQSRULESDHQSHQS:";
7 |
8 | void enter(Output client, String pseudo);
9 |
10 | void broadcast(Output client, String message);
11 |
12 | void leave(Output client);
13 |
14 | boolean waitForAbandon(long count, TimeUnit timeUnit) throws InterruptedException;
15 | }
16 |
--------------------------------------------------------------------------------
/src/test/java/net/bourgau/philippe/concurrency/kata/DotOutput.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata;
2 |
3 | import net.bourgau.philippe.concurrency.kata.common.Output;
4 |
5 | import java.util.concurrent.atomic.AtomicInteger;
6 |
7 | public class DotOutput implements Output {
8 | private AtomicInteger count = new AtomicInteger();
9 |
10 | @Override
11 | public void write(String line) {
12 | if (count.incrementAndGet() % 10000 == 0) {
13 | System.out.print(".");
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/test/java/net/bourgau/philippe/concurrency/kata/MemoryOutput.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata;
2 |
3 | import net.bourgau.philippe.concurrency.kata.common.Output;
4 |
5 | public class MemoryOutput implements Output {
6 |
7 | private final StringBuilder text;
8 |
9 | public MemoryOutput() {
10 | text = new StringBuilder();
11 | }
12 |
13 | public void write(String line) {
14 | text.append(line).append("\n");
15 | }
16 |
17 | @Override
18 | public String toString() {
19 | return text.toString();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Vagrantfiles/intellij/project.default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/java/net/bourgau/philippe/concurrency/kata/common/Message.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata.common;
2 |
3 | public final class Message {
4 | public static String welcome(String pseudo) {
5 | return String.format("Welcome %s !", pseudo);
6 | }
7 |
8 | public static String signed(String name, String message) {
9 | return String.format("%s > %s", name, message);
10 | }
11 |
12 | public static String exit(String name) {
13 | return String.format("%s left", name);
14 | }
15 |
16 | public static String selfExit() {
17 | return "You left the room";
18 | }
19 |
20 | public static String login(String message) {
21 | return ChatRoom.GOD_PREFIX + message;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/net/bourgau/philippe/concurrency/kata/CountingOutput.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata;
2 |
3 | import net.bourgau.philippe.concurrency.kata.common.Output;
4 | import org.fest.assertions.api.Assertions;
5 | import org.fest.assertions.api.IntegerAssert;
6 |
7 | import java.util.concurrent.atomic.AtomicInteger;
8 |
9 | public class CountingOutput implements Output {
10 | private AtomicInteger messageCount = new AtomicInteger();
11 |
12 | @Override
13 | public void write(String line) {
14 | messageCount.incrementAndGet();
15 | }
16 |
17 | public void reset() {
18 | messageCount.set(0);
19 | }
20 |
21 | public IntegerAssert assertMessageCount() {
22 | return Assertions.assertThat(messageCount.get());
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/net/bourgau/philippe/concurrency/kata/csp/ChatRoomCoRoutine.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata.csp;
2 |
3 | import net.bourgau.philippe.concurrency.kata.common.ChatRoom;
4 |
5 | public class ChatRoomCoRoutine {
6 |
7 | private final Channel> messageChannel;
8 | private final ChatRoom chatRoom;
9 |
10 | public ChatRoomCoRoutine(final ChatRoom chatRoom, Channel> channel) {
11 | this.chatRoom = chatRoom;
12 | this.messageChannel = channel;
13 | }
14 |
15 | public void run() {
16 | messageChannel.pop(new Action>() {
17 |
18 | @Override
19 | protected void doExecute(Action message) throws Exception {
20 | message.execute(chatRoom);
21 | run();
22 | }
23 | });
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/net/bourgau/philippe/concurrency/kata/monothread/MonoThread.java:
--------------------------------------------------------------------------------
1 | package net.bourgau.philippe.concurrency.kata.monothread;
2 |
3 | import net.bourgau.philippe.concurrency.kata.common.*;
4 |
5 | import java.util.HashMap;
6 | import java.util.concurrent.TimeUnit;
7 |
8 | public class MonoThread implements Implementation {
9 |
10 | @Override
11 | public InProcessChatRoom startNewChatRoom() {
12 | return new InProcessChatRoom(new HashMap