From 62636e844f26b2b1e584b2fd8f2b78ef758d8711 Mon Sep 17 00:00:00 2001
From: Matt Bovel <matthieu@bovel.net>
Date: Tue, 17 May 2022 15:25:08 +0200
Subject: [PATCH] Add exercises 5

---
 exercises/exercise-1.md |  2 +-
 exercises/exercise-2.md |  2 +-
 exercises/exercise-4.md |  3 +-
 exercises/exercise-5.md | 74 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 78 insertions(+), 3 deletions(-)
 create mode 100644 exercises/exercise-5.md

diff --git a/exercises/exercise-1.md b/exercises/exercise-1.md
index b22fc74..11ddb4a 100644
--- a/exercises/exercise-1.md
+++ b/exercises/exercise-1.md
@@ -1,4 +1,4 @@
-# Exercise 1
+# Exercise Session 1
 
 # Problem 1: Introduction to Concurrency
 
diff --git a/exercises/exercise-2.md b/exercises/exercise-2.md
index bc51fbe..17ba314 100644
--- a/exercises/exercise-2.md
+++ b/exercises/exercise-2.md
@@ -1,4 +1,4 @@
-# Exercise 2
+# Exercise Session 2
 
 # Problem 1: Aggregate
 
diff --git a/exercises/exercise-4.md b/exercises/exercise-4.md
index f82f15c..cb1a551 100644
--- a/exercises/exercise-4.md
+++ b/exercises/exercise-4.md
@@ -1,4 +1,5 @@
-# Exercise 4
+# Exercise Session 4
+
 ## Problem 1: Implementing `map` and `filter` on Futures
 
 In this exercise, you will come up with an implementation of the `map` and `filter` methods of `MyFuture`. The `MyFuture` trait is a simplified version of the `Future` trait from the Scala standard library, with a single abstract method:
diff --git a/exercises/exercise-5.md b/exercises/exercise-5.md
new file mode 100644
index 0000000..f4ff9ff
--- /dev/null
+++ b/exercises/exercise-5.md
@@ -0,0 +1,74 @@
+# Exercise Session 5
+
+## Problem 1: Message Processing Semantics
+
+Consider the following actor system:
+
+```scala
+enum Protocol:
+  case Write(value: Int)
+  case Read(requester: ActorRef)
+import Protocol.*
+
+enum Responses:
+  case Answer(value: Int)
+import Responses.*
+
+
+class Memory extends Actor:
+  var value = 0
+
+  override def receive: Receive = {
+    case Write(newValue) => value = newValue
+    case Read(requester) => requester ! Answer(value)
+  }
+
+class Client(memory: ActorRef) extends Actor:
+  override def receive: Receive = { case Answer(value) =>
+    println(value)
+  }
+
+class MyProxy(memory: ActorRef) extends Actor:
+  override def receive: Receive = { case message =>
+    memory ! message
+  }
+```
+
+### Problem 1.1
+
+And the following test:
+
+```scala
+@main def problem1_1 =
+  for _ <- 1 to 1000 do
+    val system = ActorSystem("example")
+    try
+      val memory = system.actorOf(Props(Memory()))
+      val client = system.actorOf(Props(Client(memory)))
+      memory ! Write(1)
+      memory ! Read(client)
+    finally system.terminate()
+```
+
+What are the possible values printed by the `println` command in the `Client` actor? Why?
+
+### Problem 1.2
+
+Now, consider the following test:
+
+```scala
+@main def problem1_2 =
+  for _ <- 1 to 1000 do
+    val system = ActorSystem("example")
+    try
+      val memory = system.actorOf(Props(Memory()))
+      val proxy  = system.actorOf(Props(MyProxy(memory)))
+      val client = system.actorOf(Props(Client(memory)))
+      proxy ! Read(client)
+      memory ! Write(1)
+    finally system.terminate()
+```
+
+1. What are the possible values printed by the `println` command in the `Client2` actor? Why?
+2. Would the output be different if the commands annotated with `XXX` were issued in the other order?
+3. What if both messages are sent through the `Proxy` actor?
-- 
GitLab