Choreographies are a way of describing communicating systems as global programs
A
x = crunch()
send("B",x)
B
x = receive("A")
y = crunch(x)
A
x = crunch()
send("B",x)
B
x = receive("a")
y = crunch(x)
send("A",y)
A
x = crunch()
send("B",x)
y = receive("B")
B
x = receive("A")
y = crunch(x)
send("A",y)
A
x = crunch()
send("B",x)
y = receive("B")
if y > 100:
z = crunch(y)
send("B",z)
else:
exit 1
B
x = receive("A")
y = crunch(x)
send("A",y)
A
x = crunch()
send("B",x)
y = receive("B")
if y > 100:
z = crunch(y)
send("B",z)
else:
exit 1
B
x = receive("A")
y = crunch(x)
send("A",y)
if y > 100:
z = receive("A")
...
else:
exit 1
A
x = crunch()
send("B",x)
y = receive("B")
z = crunch(y)
if z > 100:
send("B",z)
else:
exit 1
B
x = receive("A")
y = crunch(x)
send("A",y)
let x@A = crunch()
A[x] -> B.x
let y@B = crunch(x)
A
x = crunch()
send("B",x)
B
x = receive("A")
y = crunch(x)
let x@A = crunch()
A[x] -> B.x
let y@B = crunch(x)
A
x = crunch()
send("B",x)
y = receive("B")
B
x = receive("A")
y = crunch(x)
send("A",y)
let x@A = crunch()
A[x] -> B.x
let y@B = crunch(x)
B[y] -> A.y
A
x = crunch()
send("B",x)
y = receive("B")
B
x = receive("A")
y = crunch(x)
send("A",y)
let x@A = crunch()
A[x] -> B.x
let y@B = crunch(x)
B[y] -> A.y
A
...
if y > 100:
z = crunch(y)
send("B",z)
else:
exit 1
B
...
if y > 100:
z = receive("A")
...
else:
exit 1
//...
let v@A = y > 100
if v@A {
A<T> -> B
let z@A = crunch(y)
A.[z] -> B.z
//...
} else {
A<F> -> B
//DONE
}
A
...
if y > 100:
z = crunch(y)
send("B",z)
else:
exit 1
B
...
if y > 100:
z = receive("A")
...
else:
exit 1
//...
let v@A = y > 100
if v@A {
A<T> -> B
let z@A = crunch(y)
A.[z] -> B.z
//...
} else {
A<F> -> B
//DONE
}
Syntax
G | ::= |
A[x] -> B.y; G | (com) |
| |
A<b> -> B; G | (sel) | |
| |
Let x@A = foo(..); G | (let) | |
| |
If x@A
Then G
Else G | (if) | |
| |
End | (end) |
Semantics
Where:
Communication
A[x] -> B.y;C
Communication
S
A[x] -> B.y;C
Communication
S(A,x) = d
A[x] -> B.y;C
Communication
A[x] -> B.y;C
S[(B,y)|->d]
Communication
S[(B,y)|->d]
C
Features
Concurrency
Concurrency
A[x] -> B.y
P[z] -> Q.w
✅
A[x] -> B.y
P[z] -> Q.w
C[m] -> D.k
A[x] -> B.y
✅
C[m] -> D.k
✅
P[z] -> Q.w
C[m] -> D.k
Asyncrony
Asyncrony
A[x] -> B.y
P[z] -> A.w
A[m] -> D.k
Asyncrony
A[x] -> B.y
P[z] -> A.w
A[m] -> D.k
✅
P[z] -> A.w
A[m] -> D.k
Asyncrony
A[x] -> B.y
P[z] -> A.w
A[m] -> D.k
✅ -> B.y
P[z] -> A.w
A[m] -> D.k
✅ -> ✅
P[z] -> A.w
A[m] -> D.k
Asyncrony
A[x] -> B.y
P[z] -> A.w
A[m] -> D.k
✅ -> B.y
✅
A[m] -> D.k
✅
P[z] -> A.w
A[m] -> D.k
Asyncrony
A[x] -> B.y
P[z] -> A.w
❌
A[x] -> B.y
P[z] -> A.w
A[m] -> D.k
A[x] -> B.y
✅
A[m] -> D.k
✅
P[z] -> A.w
A[m] -> D.k
Projection
let x@A = crunch()
let y@B = crunch()
A[x] -> B.x
B[y] -> A.y
let x@A = crunch()
let y@B = crunch()
A[x] -> B.x
B[y] -> A.y
A
x = crunch()
let x@A = crunch()
let y@B = crunch()
A[x] -> B.x
B[y] -> A.y
A
x = crunch()
B
y = crunch()
let x@A = crunch()
let y@B = crunch()
A[x] -> B.x
B[y] -> A.y
A
x = crunch()
send("A",x)
B
y = crunch()
x = receive("A")
let x@a = crunch()
let y@b = crunch()
A[x] -> B.x
B[y] -> A.y
A
x = crunch()
send("B",x)
y = receive("B")
B
y = crunch()
x = receive("A")
send("A",y)
Confluence
Deadlock-freedom
$\text{fv}(c) \subseteq \text{fv}(s) \implies \exists{s'.}{(s,c) \rightarrow^{\ast} (s',end)}$ |
A[x] -> B.x
B[y] -> A.y
A[x] -> B.x
B[y] -> A.y
A[x] -> B.x
B[y] -> A.y
An endpoint language
EPN | ::= |
<p,s,q,EP> | (Single) |
| |
<p,s,q,EP> || EPN | (Parallel) |
Where:
p
) is a process names
) is a mappings from varible names to values
representing the process state,q
) is a queue of unread messagesEP
) is the endpoint codeEP | ::= |
Send p x; EP |
| |
Receive p y; EP | |
| |
InternalChoice p b; EP | |
| |
ExternalChoice p EP EP | |
| |
Let v f vl in EP | |
| |
If v Then EP
Else EP | |
| |
End |
<A,sa,qa,>
Send "B" x
...
sa(x) = d
<B,sb,qb,>
Receive "A" x
...
<A,sa,qa,>
...
sa(x) = d
<B,sb,qb',>
Receive "A" x
...
qb' = ("A",d)::qb
<A,sa,qa,>
...
<B,sb',qb,>
...
sb' = sb[x |-> d]
project(p,c) = (succ,EP)
Where:
p
) is a process namec
) is a choreographyEP
) is a single endpointsucc
) is a boolean signaling success
Definition project_def:
...
∧ project proc (Com p1 v1 p2 v2 c) =
if proc = p1 ∧ proc = p2
then (F,Nil)
else if proc = p1
then Send p2 v1 <Γ> project proc c
else if proc = p2
then Receive p1 v2 <Γ> project proc c
else project proc c
...
Semantic preservation
$(s,c)\xrightarrow{}(s',c')$ |
$\exists{c'',s''.\;}(s',c')\rightarrow^{\ast}(s'',c'')\,\land\, [\![s,c]\!]\rightarrow^{\ast}[\![s'',c'']\!]$ |
Semantic reflection
$[\![s,c]\!]\xrightarrow{}epn$ |
$\exists{c',s'.\;}epn\rightarrow^{\ast}[\![s',c']\!]\,\land\, (s,c)\rightarrow^{\ast}(s',c')$ |
EPN
EPN
Selection
Payload
IntChoice b p
...
Let fv = b
Send p fv
...
ExternalChoice p e1 e2
Receive p fv
If fv Then e1 Else e2
Send p vlm
...
Send p v
Send p l
Send p m
...
Receive p vlm
...
Receive p v
Receive p l
Receive p m
...
EPN
Selection
Payload
send
and receive
ffi calls