From 2e7d2461e11b92c688a466ce24e1362e2454025e Mon Sep 17 00:00:00 2001 From: AlexZangerle Date: Mon, 19 Jan 2026 12:56:11 +0100 Subject: [PATCH 1/5] feat: add chameneos example --- chameneos/chameneos.pkl | 53 +++++++++++++++++++++++++++++++++++++++++ chameneos/main.pkl | 14 +++++++++++ chameneos/mall.pkl | 53 +++++++++++++++++++++++++++++++++++++++++ chameneos/services.pkl | 4 ++++ 4 files changed, 124 insertions(+) create mode 100644 chameneos/chameneos.pkl create mode 100644 chameneos/main.pkl create mode 100644 chameneos/mall.pkl create mode 100644 chameneos/services.pkl diff --git a/chameneos/chameneos.pkl b/chameneos/chameneos.pkl new file mode 100644 index 0000000..8c4e0e2 --- /dev/null +++ b/chameneos/chameneos.pkl @@ -0,0 +1,53 @@ +import + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + +sm = new csml.StateMachine { + transient { + ["chameneosId"] = "std:getUniqueId()" + ["color"] = "std:getRandomColor()" + ["individualMeetingCounter"] = "0" + } + states { + ["requestingPartner"] = new csml.Initial { + entry { + new csml.Raise { + event = new csml.Global { + topic = "requestingPartner" + data { ["chameneosId"] = "chameneosId"; ["chameneosColor"] = "color" } + } + } + } + on { + ["matchMade"] = new csml.Transition { + to = "matchFound" + iif = "$chameneos == chameneosId" + } + ["change"] = new csml.Transition { + to = "requestingPartner" + iif = "$partner == chameneosId" + do { + new csml.Eval { expression = "color = std:complement(color, $color)" } + new csml.Eval { expression = "individualMeetingCounter = individualMeetingCounter + 1" } + } + } + ["done"] = new csml.Transition { + to = "done" + } + } + } + ["matchFound"] = new csml.State { + entry { + new csml.Eval { expression = "color = std:complement(color, $color)" } + new csml.Eval { expression = "individualMeetingCounter = individualMeetingCounter + 1" } + new csml.Raise { + event = new csml.Global { + topic = "change" + data { ["partner"] = "$partner"; ["color"] = "color" } + } + } + } + always { new csml.Transition { to = "requestingPartner" } } + } + ["done"] = new csml.Terminal {} + } +} diff --git a/chameneos/main.pkl b/chameneos/main.pkl new file mode 100644 index 0000000..cf5bda8 --- /dev/null +++ b/chameneos/main.pkl @@ -0,0 +1,14 @@ +amends + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + +import "chameneos.pkl" +import "defs.pkl" +import "mall.pkl" + +version = "4.0.0" +stateMachines { + ["mall"] = mall.sm + for (_def in defs.chameneos) { + [_def] = chameneos.sm + } +} diff --git a/chameneos/mall.pkl b/chameneos/mall.pkl new file mode 100644 index 0000000..283863b --- /dev/null +++ b/chameneos/mall.pkl @@ -0,0 +1,53 @@ +import + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + +sm = new csml.StateMachine { + transient { + ["waitingList"] = "[...]" + ["meetingCounter"] = "0" + } + states { + ["waitingForChameneos"] = new csml.Initial { + on { + ["requestingPartner"] = new csml.Transition { + to = "waitingForChameneos" + iif = "waitingList.isEmpty() && meetingCounter < 1000000" + do { + new csml.Eval { + expression = "waitingList = std:addToList(\("waitingList"), $chameneosId)" + } + } + or = "scheduleMeeting" + } + } + } + ["scheduleMeeting"] = new csml.State { + always { + new csml.Transition { + to = "waitingForChameneos" + iif = "!waitingList.isEmpty() && meetingCounter < 1000000" + do { + new csml.Eval { expression = "meetingCounter = meetingCounter + 1" } + new csml.Raise { + event = new csml.Global { + topic = "matchMade" + data { + ["chameneos"] = "waitingList.get(0)" + ["partner"] = "$chameneosId" + ["color"] = "$chameneosColor" + } + } + } + new csml.Eval { expression = "waitingList = std:removeFirst(\("waitingList"))" } + } + or = "done" + } + } + } + ["done"] = new csml.Terminal { + entry { + new csml.Raise { event = new csml.Global { topic = "done" } } + } + } + } +} diff --git a/chameneos/services.pkl b/chameneos/services.pkl new file mode 100644 index 0000000..07c151f --- /dev/null +++ b/chameneos/services.pkl @@ -0,0 +1,4 @@ +amends + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/bindings.pkl" + +bindings {} From 00f9812efd8e5648de9e4893a75709e6173ef74a Mon Sep 17 00:00:00 2001 From: AlexZangerle Date: Wed, 21 Jan 2026 13:26:51 +0100 Subject: [PATCH 2/5] feat: add big example --- big/big.pkl | 92 +++++++++++++++++++++++++++++++ big/defs.pkl | 1 + big/main.pkl | 14 +++++ big/services.pkl | 4 ++ big/sink.pkl | 59 ++++++++++++++++++++ pingpong/benchmark/Akka.txt | 31 ----------- pingpong/benchmark/AkkaRemote.txt | 30 ---------- 7 files changed, 170 insertions(+), 61 deletions(-) create mode 100644 big/big.pkl create mode 100644 big/defs.pkl create mode 100644 big/main.pkl create mode 100644 big/services.pkl create mode 100644 big/sink.pkl delete mode 100644 pingpong/benchmark/Akka.txt delete mode 100644 pingpong/benchmark/AkkaRemote.txt diff --git a/big/big.pkl b/big/big.pkl new file mode 100644 index 0000000..3ac9522 --- /dev/null +++ b/big/big.pkl @@ -0,0 +1,92 @@ +import + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + +sm = new csml.StateMachine { + transient { + ["bigId"] = "std:getSequentialId()" + ["target"] = "''" + ["otherBigs"] = "[...]" + ["pingCounter"] = "0" + ["pongCounter"] = "0" + } + states { + ["registerBig"] = new csml.Initial { + entry { + new csml.Raise { + event = new csml.Global { topic = "registerBig"; data { ["bigId"] = "bigId" } } + } + } + on { + ["allBigsRegistered"] = new csml.Transition { + to = "sendPing" + do { + new csml.Eval { expression = "otherBigs = std:getAllStateMachines()" } + new csml.Eval { + expression = "otherBigs = std:removeFromList(\("otherBigs"), \("bigId"))" + } + } + } + } + } + ["sendPing"] = new csml.State { + always { + new csml.Transition { + to = "waitForPingOrPong" + iif = "pingCounter < 20000" + do { + new csml.Eval { expression = "pingCounter = pingCounter + 1" } + new csml.Eval { expression = "target = std:takeRandom(\("otherBigs"))" } + new csml.Raise { + event = new csml.Global { + topic = "ping" + data { ["sender"] = "bigId"; ["receiver"] = "target" } + } + } + } + or = "receiveRemaining" + } + } + } + ["waitForPingOrPong"] = new csml.State { + on { + ["ping"] = new csml.Transition { + iif = "$sender != bigId && $receiver == bigId" + do { + new csml.Raise { + event = new csml.Global { + topic = "pong" + data { ["sender"] = "bigId"; ["receiver"] = "$sender" } + } + } + } + } + ["pong"] = new csml.Transition { + iif = "$receiver == bigId && $sender == target" + to = "sendPing" + } + } + } + ["receiveRemaining"] = new csml.State { + entry { + new csml.Raise { event = new csml.Global { topic = "donePinging" } } + } + on { + ["ping"] = new csml.Transition { + iif = "$sender != bigId && $receiver == bigId" + do { + new csml.Raise { + event = new csml.Global { + topic = "pong" + data { ["sender"] = "bigId"; ["receiver"] = "$sender" } + } + } + } + } + ["shutdown"] = new csml.Transition { + to = "done" + } + } + } + ["done"] = new csml.Terminal {} + } +} diff --git a/big/defs.pkl b/big/defs.pkl new file mode 100644 index 0000000..b9bdb2c --- /dev/null +++ b/big/defs.pkl @@ -0,0 +1 @@ +bigs = List("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11") diff --git a/big/main.pkl b/big/main.pkl new file mode 100644 index 0000000..fc70794 --- /dev/null +++ b/big/main.pkl @@ -0,0 +1,14 @@ +amends + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + +import "big.pkl" +import "defs.pkl" +import "sink.pkl" + +version = "4.0.0" +stateMachines { + ["sink"] = sink.sm + for (_def in defs.bigs) { + [_def] = big.sm + } +} diff --git a/big/services.pkl b/big/services.pkl new file mode 100644 index 0000000..07c151f --- /dev/null +++ b/big/services.pkl @@ -0,0 +1,4 @@ +amends + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/bindings.pkl" + +bindings {} diff --git a/big/sink.pkl b/big/sink.pkl new file mode 100644 index 0000000..f1f64e2 --- /dev/null +++ b/big/sink.pkl @@ -0,0 +1,59 @@ +import + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + +sm = new csml.StateMachine { + transient { + ["registered"] = "''" + ["registeredCounter"] = "0" + ["doneCounter"] = "0" + ["cumulatedPongCounter"] = "0" + } + states { + ["registerBigs"] = new csml.Initial { + on { + ["registerBig"] = new csml.Transition { + to = "evaluateAllBigsReceived" + do { + new csml.Eval { expression = "registeredCounter = registeredCounter + 1" } + new csml.Eval { expression = "registered = std:registerStateMachine(\("$bigId"))" } + } + } + } + } + ["evaluateAllBigsReceived"] = new csml.State { + always { + new csml.Transition { + to = "waitingForBigs" + iif = "registeredCounter == 12" + do { + new csml.Raise { event = new csml.Global { topic = "allBigsRegistered" } } + } + or = "registerBigs" + } + } + } + ["waitingForBigs"] = new csml.State { + on { + ["donePinging"] = new csml.Transition { + to = "isFinal" + do { + new csml.Eval { expression = "doneCounter = doneCounter + 1" } + } + } + } + } + ["isFinal"] = new csml.State { + always { + new csml.Transition { + to = "done" + iif = "doneCounter == 12" + do { + new csml.Raise { event = new csml.Global { topic = "shutdown" } } + } + or = "waitingForBigs" + } + } + } + ["done"] = new csml.Terminal {} + } +} diff --git a/pingpong/benchmark/Akka.txt b/pingpong/benchmark/Akka.txt deleted file mode 100644 index f8f6882..0000000 --- a/pingpong/benchmark/Akka.txt +++ /dev/null @@ -1,31 +0,0 @@ -Number of pings: 50.000 -Execution - Iterations: -PingPongAkkaActorBenchmark Iteration-0: 316.151 ms -PingPongAkkaActorBenchmark Iteration-1: 118.366 ms -PingPongAkkaActorBenchmark Iteration-2: 77.245 ms -PingPongAkkaActorBenchmark Iteration-3: 84.737 ms -PingPongAkkaActorBenchmark Iteration-4: 70.632 ms -PingPongAkkaActorBenchmark Iteration-5: 76.096 ms -PingPongAkkaActorBenchmark Iteration-6: 72.107 ms -PingPongAkkaActorBenchmark Iteration-7: 67.815 ms -PingPongAkkaActorBenchmark Iteration-8: 64.724 ms -PingPongAkkaActorBenchmark Iteration-9: 65.730 ms -PingPongAkkaActorBenchmark Iteration-10: 68.262 ms -PingPongAkkaActorBenchmark Iteration-11: 64.844 ms - - -Execution - Summary: - Total executions = 12 - Filtered executions = 10 -PingPongAkkaActorBenchmark Best Time: 64.724 ms -PingPongAkkaActorBenchmark Worst Time: 84.737 ms -PingPongAkkaActorBenchmark Median: 69.447 ms -PingPongAkkaActorBenchmark Arith. Mean Time: 71.219 ms -PingPongAkkaActorBenchmark Geo. Mean Time: 70.966 ms -PingPongAkkaActorBenchmark Harmonic Mean Time: 70.724 ms -PingPongAkkaActorBenchmark Std. Dev Time: 6.142 ms -PingPongAkkaActorBenchmark Lower Confidence: 67.412 ms -PingPongAkkaActorBenchmark Higher Confidence: 75.026 ms -PingPongAkkaActorBenchmark Error Window: 3.807 ms (5.345 percent) -PingPongAkkaActorBenchmark Coeff. of Variation: 0.086 -PingPongAkkaActorBenchmark Skewness: 0.979 \ No newline at end of file diff --git a/pingpong/benchmark/AkkaRemote.txt b/pingpong/benchmark/AkkaRemote.txt deleted file mode 100644 index 8f63738..0000000 --- a/pingpong/benchmark/AkkaRemote.txt +++ /dev/null @@ -1,30 +0,0 @@ -Number of pings: 50.000 -Execution - Iterations: -PingPongAkkaActorBenchmark Iteration-0: 30511.704 ms -PingPongAkkaActorBenchmark Iteration-1: 25736.073 ms -PingPongAkkaActorBenchmark Iteration-2: 30145.372 ms -PingPongAkkaActorBenchmark Iteration-3: 31287.985 ms -PingPongAkkaActorBenchmark Iteration-4: 33002.205 ms -PingPongAkkaActorBenchmark Iteration-5: 30022.782 ms -PingPongAkkaActorBenchmark Iteration-6: 31745.709 ms -PingPongAkkaActorBenchmark Iteration-7: 32723.041 ms -PingPongAkkaActorBenchmark Iteration-8: 32083.870 ms -PingPongAkkaActorBenchmark Iteration-9: 29523.999 ms -PingPongAkkaActorBenchmark Iteration-10: 24884.690 ms -PingPongAkkaActorBenchmark Iteration-11: 28197.974 ms - -Execution - Summary: - Total executions = 12 - Filtered executions = 12 -PingPongAkkaActorBenchmark Best Time: 24884.690 ms -PingPongAkkaActorBenchmark Worst Time: 33002.205 ms -PingPongAkkaActorBenchmark Median: 30328.538 ms -PingPongAkkaActorBenchmark Arith. Mean Time: 29988.784 ms -PingPongAkkaActorBenchmark Geo. Mean Time: 29881.058 ms -PingPongAkkaActorBenchmark Harmonic Mean Time: 29767.749 ms -PingPongAkkaActorBenchmark Std. Dev Time: 2476.228 ms -PingPongAkkaActorBenchmark Lower Confidence: 28587.726 ms -PingPongAkkaActorBenchmark Higher Confidence: 31389.841 ms -PingPongAkkaActorBenchmark Error Window: 1401.058 ms (4.672 percent) -PingPongAkkaActorBenchmark Coeff. of Variation: 0.083 -PingPongAkkaActorBenchmark Skewness: -0.904 \ No newline at end of file From c681625749dc5ee3bed5189ca9cf81e4490913f7 Mon Sep 17 00:00:00 2001 From: AlexZangerle Date: Mon, 26 Jan 2026 10:47:05 +0100 Subject: [PATCH 3/5] feat: add sleepingBarber example --- sleepingBarber/barber.pkl | 59 +++----- sleepingBarber/customer.pkl | 138 ++++++------------- sleepingBarber/main.pkl | 12 +- sleepingBarber/services.pkl | 3 +- sleepingBarber/waitingRoom.pkl | 239 ++++++++++++--------------------- 5 files changed, 156 insertions(+), 295 deletions(-) diff --git a/sleepingBarber/barber.pkl b/sleepingBarber/barber.pkl index 3282012..f293d9b 100644 --- a/sleepingBarber/barber.pkl +++ b/sleepingBarber/barber.pkl @@ -1,59 +1,40 @@ import - "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/Csml.pkl" + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" -class StateMachine extends Csml.StateMachineDescription { - name = "barber" +sm = new csml.StateMachine { states { - new { - name = "sleeping" - initial = true + ["sleeping"] = new csml.Initial { entry { - new Csml.RaiseActionDescription { - event { - name = "statusSleeping" - channel = "global" - } - } + new csml.Raise { event = new csml.Global { topic = "statusSleeping" } } } on { - new { - event = "enter" - target = "cutting" + ["enter"] = new csml.Transition { + to = "cutting" + } + ["terminate"] = new csml.Transition { + to = "done" } } } - new { - name = "cutting" + ["cutting"] = new csml.State { always { - new { - guards { - new { - expression = "utility:busyWait(1000) == 1000" - } - } - actions { - new Csml.RaiseActionDescription { - event { - name = "done" + new csml.Transition { + to = "sleeping" + iif = "std:busyWait(1000)" + do { + new csml.Raise { + event = new csml.Global { + topic = "done" data { - new { - name = "customer" - value = "$customer" - } + ["customer"] = "$customer" } - channel = "global" - } - } - new Csml.RaiseActionDescription { - event { - name = "getNext" - channel = "global" } } + new csml.Raise { event = new csml.Global { topic = "getNext" } } } - target = "sleeping" } } } + ["done"] = new csml.Terminal {} } } diff --git a/sleepingBarber/customer.pkl b/sleepingBarber/customer.pkl index 2d99b51..2b7900d 100644 --- a/sleepingBarber/customer.pkl +++ b/sleepingBarber/customer.pkl @@ -1,127 +1,77 @@ -import "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/Csml.pkl" +import + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" -class StateMachine extends Csml.StateMachineDescription { - name = "customer" - local self = this - localContext { - variables { - new { - name = "counter" - value = "0" - } - } +sm = new csml.StateMachine { + transient { + ["counter"] = "0" + ["customerId"] = "std:getSequentialId()" } states { - new { - name = "init" - initial = true + ["init"] = new csml.Initial { on { - new { - event = "ready" - target = "requestHaircut" + ["ready"] = new csml.Transition { + to = "requestHaircut" } } } - new { - name = "requestHaircut" + ["requestHaircut"] = new csml.State { entry { - new Csml.RaiseActionDescription { - event { - name = "customerEnter" + new csml.Raise { + event = new csml.Global { + topic = "customerEnter" data { - new { - name = "customer" - value = self.name - } + ["customer"] = "customerId" } - channel = "global" } } } on { - new { - event = "full" - guards { - new { - expression = "$customer == \(self.name)" - } - } - target = "requestHaircut" + ["full"] = new csml.Transition { + to = "requestHaircut" + iif = "$customer == customerId" } - new { - event = "enter" - guards { - new { - expression = "$customer == \(self.name)" - } - } - target = "gettingHaircut" + ["enter"] = new csml.Transition { + to = "gettingHaircut" + iif = "$customer == customerId" } - new { - event = "waiting" - guards { - new { - expression = "$customer == \(self.name)" - } - } - target = "waiting" + ["waiting"] = new csml.Transition { + to = "waiting" + iif = "$customer == customerId" } } } - new { - name = "gettingHaircut" + ["gettingHaircut"] = new csml.State { entry { - new Csml.AssignActionDescription { - variable = new { - name = "counter" - value = "counter + 1" - } - } + new csml.Eval { expression = "counter = counter + 1" } } on { - new { - event = "done" - guards { - new { - expression = "$customer == \(self.name)" - } - new { - expression = "counter < 333" - } - } - target = "requestHaircut" + ["done"] = new csml.Transition { + to = "evaluateCounter" + iif = "$customer == customerId" } - new { - event = "done" - guards { - new { - expression = "$customer == \(self.name)" - } - new { - expression = "counter >= 333" - } - } - target = "leave" + } + } + ["evaluateCounter"] = new csml.State { + always { + new csml.Transition { + to = "requestHaircut" + iif = "counter < 333" + or = "leave" } } } - new { - name = "waiting" + ["waiting"] = new csml.State { on { - new { - event = "enter" - guards { - new { - expression = "$customer == \(self.name)" - } - } - target = "gettingHaircut" + ["enter"] = new csml.Transition { + to = "gettingHaircut" + iif = "$customer == customerId" } } } - new { - name = "leave" - terminal = true + ["leave"] = new csml.Terminal { + entry { + new csml.Raise { event = new csml.Global { topic = "doneCutting" } } + } } } } diff --git a/sleepingBarber/main.pkl b/sleepingBarber/main.pkl index 86655d0..192f51e 100644 --- a/sleepingBarber/main.pkl +++ b/sleepingBarber/main.pkl @@ -1,16 +1,16 @@ -amends "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/Csml.pkl" +amends + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" import "barber.pkl" import "customer.pkl" import "defs.pkl" import "waitingRoom.pkl" -name = "benchmark" -version = "3.0.0" +version = "4.0.0" stateMachines { - new barber.StateMachine {} + ["barber"] = barber.sm for (_def in defs.customers) { - new customer.StateMachine { name = _def } + [_def] = customer.sm } - new waitingRoom.StateMachine {} + ["waitingRoom"] = waitingRoom.sm } diff --git a/sleepingBarber/services.pkl b/sleepingBarber/services.pkl index 48fc97f..07c151f 100644 --- a/sleepingBarber/services.pkl +++ b/sleepingBarber/services.pkl @@ -1,3 +1,4 @@ -amends "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/ServiceImplementationBindings.pkl" +amends + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/bindings.pkl" bindings {} diff --git a/sleepingBarber/waitingRoom.pkl b/sleepingBarber/waitingRoom.pkl index 94f49ba..ac398c3 100644 --- a/sleepingBarber/waitingRoom.pkl +++ b/sleepingBarber/waitingRoom.pkl @@ -1,193 +1,122 @@ -import "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/Csml.pkl" +import + "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" -class StateMachine extends Csml.StateMachineDescription { - name = "waitingRoom" - localContext { - variables { - new { - name = "waitingCustomers" - value = "[...]" - } - new { - name = "barberStatus" - value = "''" - } - } +sm = new csml.StateMachine { + transient { + ["waitingCustomers"] = "[...]" + ["barberStatus"] = "''" + ["doneCounter"] = "0" } states { - new { - name = "process" - initial = true - entry { - new Csml.RaiseActionDescription { - event { - name = "ready" - channel = "global" + ["init"] = new csml.Initial { + always { + new csml.Transition { + to = "process" + do { + new csml.Raise { event = new csml.Global { topic = "ready" } } } } } + } + ["process"] = new csml.Initial { on { - new { - event = "customerEnter" - guards { - new { - expression = "waitingCustomers.size() == 3" - } - } - actions { - new Csml.RaiseActionDescription { - event { - name = "full" + ["customerEnter"] = new csml.Transition { + to = "process" + iif = "waitingCustomers.size() == 3" + do { + new csml.Raise { + event = new csml.Global { + topic = "full" data { - new { - name = "customer" - value = "$customer" - } + ["customer"] = "$customer" } - channel = "global" } } } + or = "evaluateWaitingRoom" } - new { - event = "customerEnter" - guards { - new { - expression = "waitingCustomers.isEmpty()" - } - new { - expression = "barberStatus == 'sleeping'" - } - } - actions { - new Csml.RaiseActionDescription { - event { - name = "enter" + ["getNext"] = new csml.Transition { + iif = "!waitingCustomers.isEmpty()" + do { + new csml.Raise { + event = new csml.Global { + topic = "enter" data { - new { - name = "customer" - value = "$customer" - } + ["customer"] = "waitingCustomers.get(0)" } - channel = "global" } } - new Csml.AssignActionDescription { - variable = new { - name = "barberStatus" - value = "'busy'" - } + new csml.Eval { + expression = "waitingCustomers = std:removeFirst(\("waitingCustomers"))" } + new csml.Eval { expression = "barberStatus = 'busy'" } } } - new { - event = "customerEnter" - guards { - new { - expression = "waitingCustomers.isEmpty()" - } - new Csml.GuardDescription { - expression = "barberStatus == 'busy'" - } - } - actions { - new Csml.AssignActionDescription { - variable = new { - name = "waitingCustomers" - value = "utility:addToList(\("waitingCustomers"), $customer)" - } - } - new Csml.RaiseActionDescription { - event { - name = "waiting" - data { - new { - name = "customer" - value = "$customer" - } - } - channel = "global" - } - } + ["statusSleeping"] = new csml.Transition { + do { + new csml.Eval { expression = "barberStatus = 'sleeping'" } } } - new { - event = "customerEnter" - guards { - new { - expression = "waitingCustomers.size() != 3" - } - new { - expression = "!waitingCustomers.isEmpty()" - } - } - actions { - new Csml.AssignActionDescription { - variable = new { - name = "waitingCustomers" - value = "utility:addToList(\("waitingCustomers"), $customer)" - } - } - new Csml.RaiseActionDescription { - event { - name = "waiting" + ["doneCutting"] = new csml.Transition { + to = "process" + iif = "doneCounter < 14" + or = "terminate" + } + } + } + ["evaluateWaitingRoom"] = new csml.State { + always { + new csml.Transition { + to = "evaluateBarberStatus" + iif = "waitingCustomers.isEmpty()" + or = "addToWaitingRoom" + } + } + } + ["evaluateBarberStatus"] = new csml.State { + always { + new csml.Transition { + to = "process" + iif = "barberStatus == 'sleeping'" + do { + new csml.Raise { + event = new csml.Global { + topic = "enter" data { - new { - name = "customer" - value = "$customer" - } + ["customer"] = "$customer" } - channel = "global" } } + new csml.Eval { expression = "barberStatus = 'busy'" } } + or = "addToWaitingRoom" } - new { - event = "getNext" - guards { - new { - expression = "!waitingCustomers.isEmpty()" - } - } - actions { - new Csml.RaiseActionDescription { - event { - name = "enter" + } + } + ["addToWaitingRoom"] = new csml.State { + always { + new csml.Transition { + to = "process" + do { + new csml.Eval { + expression = "waitingCustomers = std:addToList(\("waitingCustomers"), $customer)" + } + new csml.Raise { + event = new csml.Global { + topic = "waiting" data { - new { - name = "customer" - value = "waitingCustomers.get(0)" - } + ["customer"] = "$customer" } - channel = "global" - } - } - new Csml.AssignActionDescription { - variable = new { - name = "waitingCustomers" - value = "utility:removeFirst(\("waitingCustomers"))" - } - } - new Csml.AssignActionDescription { - variable = new { - name = "barberStatus" - value = "'busy'" - } - } - } - } - new { - event = "statusSleeping" - actions { - new Csml.AssignActionDescription { - variable = new { - name = "barberStatus" - value = "'sleeping'" } } } } } } + ["terminate"] = new csml.Terminal { + entry { + new csml.Raise { event = new csml.Global { topic = "terminate" } } + } + } } } From 921bb0c9da5cbe60aae079916b97d3a4f3c1f9ed Mon Sep 17 00:00:00 2001 From: AlexZangerle Date: Wed, 28 Jan 2026 13:43:22 +0100 Subject: [PATCH 4/5] fix: remove use of std functions from sleeping barber example --- sleepingBarber/barber.pkl | 2 +- sleepingBarber/customer.pkl | 6 +++--- sleepingBarber/defs.pkl | 2 +- sleepingBarber/main.pkl | 4 ++-- sleepingBarber/waitingRoom.pkl | 9 ++++++--- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sleepingBarber/barber.pkl b/sleepingBarber/barber.pkl index f293d9b..62ed217 100644 --- a/sleepingBarber/barber.pkl +++ b/sleepingBarber/barber.pkl @@ -20,7 +20,7 @@ sm = new csml.StateMachine { always { new csml.Transition { to = "sleeping" - iif = "std:busyWait(1000)" + iif = "(function (){ let x = 0; while ( x < 1000) {x++}; return true})()" do { new csml.Raise { event = new csml.Global { diff --git a/sleepingBarber/customer.pkl b/sleepingBarber/customer.pkl index 2b7900d..bdb44fb 100644 --- a/sleepingBarber/customer.pkl +++ b/sleepingBarber/customer.pkl @@ -1,10 +1,10 @@ import "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" -sm = new csml.StateMachine { +function createCustomer(id: Int) = new csml.StateMachine { transient { ["counter"] = "0" - ["customerId"] = "std:getSequentialId()" + ["customerId"] = "\(id)" } states { ["init"] = new csml.Initial { @@ -55,7 +55,7 @@ sm = new csml.StateMachine { always { new csml.Transition { to = "requestHaircut" - iif = "counter < 333" + iif = "counter < 1000" or = "leave" } } diff --git a/sleepingBarber/defs.pkl b/sleepingBarber/defs.pkl index 27526ab..c755177 100644 --- a/sleepingBarber/defs.pkl +++ b/sleepingBarber/defs.pkl @@ -1 +1 @@ -customers = List("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15") +customers = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) diff --git a/sleepingBarber/main.pkl b/sleepingBarber/main.pkl index 192f51e..3513b38 100644 --- a/sleepingBarber/main.pkl +++ b/sleepingBarber/main.pkl @@ -9,8 +9,8 @@ import "waitingRoom.pkl" version = "4.0.0" stateMachines { ["barber"] = barber.sm - for (_def in defs.customers) { - [_def] = customer.sm + for (c in defs.customers) { + [c.toString()] = customer.createCustomer(c) } ["waitingRoom"] = waitingRoom.sm } diff --git a/sleepingBarber/waitingRoom.pkl b/sleepingBarber/waitingRoom.pkl index ac398c3..74f52e3 100644 --- a/sleepingBarber/waitingRoom.pkl +++ b/sleepingBarber/waitingRoom.pkl @@ -47,7 +47,7 @@ sm = new csml.StateMachine { } } new csml.Eval { - expression = "waitingCustomers = std:removeFirst(\("waitingCustomers"))" + expression = "waitingCustomers = waitingCustomers - [waitingCustomers.get(0)]" } new csml.Eval { expression = "barberStatus = 'busy'" } } @@ -59,7 +59,10 @@ sm = new csml.StateMachine { } ["doneCutting"] = new csml.Transition { to = "process" - iif = "doneCounter < 14" + iif = "doneCounter < 15" + do { + new csml.Eval { expression = "doneCounter = doneCounter + 1" } + } or = "terminate" } } @@ -99,7 +102,7 @@ sm = new csml.StateMachine { to = "process" do { new csml.Eval { - expression = "waitingCustomers = std:addToList(\("waitingCustomers"), $customer)" + expression = "waitingCustomers = waitingCustomers + [$customer]" } new csml.Raise { event = new csml.Global { From 24d7c494026ac6ac443cffbbf9b5b44be98bf987 Mon Sep 17 00:00:00 2001 From: AlexZangerle Date: Sun, 1 Feb 2026 14:41:30 +0100 Subject: [PATCH 5/5] feat: update sleeping barber example --- sleepingBarber/barber.pkl | 9 +++++---- sleepingBarber/customer.pkl | 16 +++++----------- sleepingBarber/defs.pkl | 2 +- sleepingBarber/main.pkl | 26 +++++++++++++++++++++----- sleepingBarber/services.pkl | 2 +- sleepingBarber/waitingRoom.pkl | 16 +++++++--------- 6 files changed, 40 insertions(+), 31 deletions(-) diff --git a/sleepingBarber/barber.pkl b/sleepingBarber/barber.pkl index 62ed217..b39b860 100644 --- a/sleepingBarber/barber.pkl +++ b/sleepingBarber/barber.pkl @@ -1,5 +1,5 @@ import - "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + "https://raw.githubusercontent.com/Frnd-me/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" sm = new csml.StateMachine { states { @@ -10,6 +10,9 @@ sm = new csml.StateMachine { on { ["enter"] = new csml.Transition { to = "cutting" + do { + new csml.Raise { event = new csml.Global { topic = "comeIn"} target = "$customer"} + } } ["terminate"] = new csml.Transition { to = "done" @@ -25,10 +28,8 @@ sm = new csml.StateMachine { new csml.Raise { event = new csml.Global { topic = "done" - data { - ["customer"] = "$customer" - } } + target = "$customer" } new csml.Raise { event = new csml.Global { topic = "getNext" } } } diff --git a/sleepingBarber/customer.pkl b/sleepingBarber/customer.pkl index bdb44fb..b3613b4 100644 --- a/sleepingBarber/customer.pkl +++ b/sleepingBarber/customer.pkl @@ -1,10 +1,9 @@ import - "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + "https://raw.githubusercontent.com/Frnd-me/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" -function createCustomer(id: Int) = new csml.StateMachine { +sm = new csml.StateMachine { transient { ["counter"] = "0" - ["customerId"] = "\(id)" } states { ["init"] = new csml.Initial { @@ -28,26 +27,22 @@ function createCustomer(id: Int) = new csml.StateMachine { on { ["full"] = new csml.Transition { to = "requestHaircut" - iif = "$customer == customerId" } - ["enter"] = new csml.Transition { + ["comeIn"] = new csml.Transition { to = "gettingHaircut" - iif = "$customer == customerId" } ["waiting"] = new csml.Transition { to = "waiting" - iif = "$customer == customerId" } } } ["gettingHaircut"] = new csml.State { entry { - new csml.Eval { expression = "counter = counter + 1" } + new csml.Eval { expression = "++counter" } } on { ["done"] = new csml.Transition { to = "evaluateCounter" - iif = "$customer == customerId" } } } @@ -62,9 +57,8 @@ function createCustomer(id: Int) = new csml.StateMachine { } ["waiting"] = new csml.State { on { - ["enter"] = new csml.Transition { + ["comeIn"] = new csml.Transition { to = "gettingHaircut" - iif = "$customer == customerId" } } } diff --git a/sleepingBarber/defs.pkl b/sleepingBarber/defs.pkl index c755177..9e1e579 100644 --- a/sleepingBarber/defs.pkl +++ b/sleepingBarber/defs.pkl @@ -1 +1 @@ -customers = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) +customers = List("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen") diff --git a/sleepingBarber/main.pkl b/sleepingBarber/main.pkl index 3513b38..d383a16 100644 --- a/sleepingBarber/main.pkl +++ b/sleepingBarber/main.pkl @@ -1,5 +1,5 @@ amends - "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + "https://raw.githubusercontent.com/Frnd-me/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" import "barber.pkl" import "customer.pkl" @@ -7,10 +7,26 @@ import "defs.pkl" import "waitingRoom.pkl" version = "4.0.0" -stateMachines { - ["barber"] = barber.sm +collaborativeStateMachine { + stateMachines { + ["barber"] = barber.sm + ["customer"] = customer.sm + ["waitingRoom"] = waitingRoom.sm + } +} +instantiate { + ["barber"] = "barber" + for (c in defs.customers) { + [c] = "customer" + } + ["waitingRoom"] = "waitingRoom" +} + +instanceData { for (c in defs.customers) { - [c.toString()] = customer.createCustomer(c) + [c] { + ["customerId"] = "'\(c)'" + } } - ["waitingRoom"] = waitingRoom.sm } +instanceSubscriptions {} diff --git a/sleepingBarber/services.pkl b/sleepingBarber/services.pkl index 07c151f..7459387 100644 --- a/sleepingBarber/services.pkl +++ b/sleepingBarber/services.pkl @@ -1,4 +1,4 @@ amends - "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/bindings.pkl" + "https://raw.githubusercontent.com/Frnd-me/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/bindings.pkl" bindings {} diff --git a/sleepingBarber/waitingRoom.pkl b/sleepingBarber/waitingRoom.pkl index 74f52e3..a9b7b4a 100644 --- a/sleepingBarber/waitingRoom.pkl +++ b/sleepingBarber/waitingRoom.pkl @@ -1,5 +1,5 @@ import - "https://raw.githubusercontent.com/CollaborativeStateMachines/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" + "https://raw.githubusercontent.com/Frnd-me/Cirrina/refs/heads/develop/src/main/resources/pkl/csm/csml.pkl" sm = new csml.StateMachine { transient { @@ -18,7 +18,7 @@ sm = new csml.StateMachine { } } } - ["process"] = new csml.Initial { + ["process"] = new csml.State { on { ["customerEnter"] = new csml.Transition { to = "process" @@ -27,10 +27,8 @@ sm = new csml.StateMachine { new csml.Raise { event = new csml.Global { topic = "full" - data { - ["customer"] = "$customer" - } } + target = "$customer" } } or = "evaluateWaitingRoom" @@ -45,6 +43,7 @@ sm = new csml.StateMachine { ["customer"] = "waitingCustomers.get(0)" } } + target = "'barber'" } new csml.Eval { expression = "waitingCustomers = waitingCustomers - [waitingCustomers.get(0)]" @@ -61,7 +60,7 @@ sm = new csml.StateMachine { to = "process" iif = "doneCounter < 15" do { - new csml.Eval { expression = "doneCounter = doneCounter + 1" } + new csml.Eval { expression = "++doneCounter" } } or = "terminate" } @@ -89,6 +88,7 @@ sm = new csml.StateMachine { ["customer"] = "$customer" } } + target = "'barber'" } new csml.Eval { expression = "barberStatus = 'busy'" } } @@ -107,10 +107,8 @@ sm = new csml.StateMachine { new csml.Raise { event = new csml.Global { topic = "waiting" - data { - ["customer"] = "$customer" - } } + target = "$customer" } } }