Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

OCaml-MPST / Global Protocol Combinators

323 views

Published on

A presentation material for PLAS Group Seminar, held at University of Kent on 16th September, 2019. A work-in-progress version of OCaml-MPST will be found at https://github.com/keigoi/ocaml-mpst

Published in: Software
  • Login to see the comments

  • Be the first to like this

OCaml-MPST / Global Protocol Combinators

  1. 1. Keigo Imai1 (with Rumyana Neykova2, Nobuko Yoshida3 and Shoji Yuen4) 1Gifu University (JP) 2Brunel University London (UK) 3Imperial College London (UK) 4Nagoya University (JP) PLAS Group Seminar, University of Kent 16th Sept. 2019 1 Global Protocol Combinators: Static Structural Multiparty Sessions Over Simply Typed Channels in OCaml
  2. 2. 2 (A supplemental slide at VeTSS 2019 workshop lightning talk)
  3. 3. Deadlocks in message-passing concurrency: Protocols prevent them! 3 A B C A ring-form multiparty communication: Concurrent programming is difficult!
  4. 4. Deadlocks in message-passing concurrency: Protocols prevent them! 4 A B C A ring-form multiparty communication: Concurrent programming is difficult! C wrong usage (direction)… ② input① output order matters…
  5. 5. Deadlocks in message-passing concurrency: Protocols prevent them! 5 A B C A ring-form multiparty communication: Concurrent programming is difficult! A B C Communication protocol! C wrong usage (direction)… ② input① output order matters…
  6. 6. Deadlocks in message-passing concurrency: Protocols prevent them! 6 A B C A ring-form multiparty communication: Concurrent programming is difficult! A B C Communication protocol! C wrong usage (direction)… ② input① output order matters… Best practice: 1. Design a communication protocol and check it 2. Focus on its local behaviours 3. Enforce protocol in the program code
  7. 7. deadlock-free? Multiparty Session Types (MPSTs): Protocol-based deadlock freedom 7 C S a "ping" protocol ③ Give concurrent processes (programs) and check their types ① Write a Global Type and check it ② Derive Local Types by End Point Projection (↾) PC | PS The system PC | PS is [Honda et al., 2008]
  8. 8. deadlock-free? Multiparty Session Types (MPSTs): Protocol-based deadlock freedom 8 C S a "ping" protocol ③ Give concurrent processes (programs) and check their types ① Write a Global Type and check it ② Derive Local Types by End Point Projection (↾) PC | PS The system PC | PS is "well-formed": protocol G iswf(G) ✔ G = C → S. S → C.end deadlock-free [Honda et al., 2008]
  9. 9. deadlock-free? Multiparty Session Types (MPSTs): Protocol-based deadlock freedom 9 C S a "ping" protocol ③ Give concurrent processes (programs) and check their types ① Write a Global Type and check it ② Derive Local Types by End Point Projection (↾) PC | PS The system PC | PS is "well-formed": protocol G iswf(G) ✔ G = C → S. S → C.end deadlock-free G↾C = LC = LSG↾S S! S? C? C! LC = LS = : "views" of the protocol [Honda et al., 2008]
  10. 10. deadlock-free? Multiparty Session Types (MPSTs): Protocol-based deadlock freedom 10 C S a "ping" protocol ③ Give concurrent processes (programs) and check their types ① Write a Global Type and check it ② Derive Local Types by End Point Projection (↾) PC | PS The system PC | PS is ✔✔ : "these processes respect the protocol"PSPC LS ⊢LC ⊢ "well-formed": protocol G iswf(G) ✔ G = C → S. S → C.end deadlock-free G↾C = LC = LSG↾S S! S? C? C! LC = LS = : "views" of the protocol [Honda et al., 2008]
  11. 11. deadlock-free? Multiparty Session Types (MPSTs): Protocol-based deadlock freedom 11 C S a "ping" protocol ③ Give concurrent processes (programs) and check their types ① Write a Global Type and check it ② Derive Local Types by End Point Projection (↾) PC | PS The system PC | PS is ✔✔ : "these processes respect the protocol"PSPC LS ⊢LC ⊢ "well-formed": protocol G iswf(G) ✔ G = C → S. S → C.end deadlock-free G↾C = LC = LSG↾S S! S? C? C! LC = LS = : "views" of the protocol deadlock-free! [Honda et al., 2008]
  12. 12. deadlock-free? Multiparty Session Types (MPSTs): Protocol-based deadlock freedom 12 C S a "ping" protocol ③ Give concurrent processes (programs) and check their types ① Write a Global Type and check it ② Derive Local Types by End Point Projection (↾) PC | PS The system PC | PS is ✔✔ : "these processes respect the protocol"PSPC LS ⊢LC ⊢ "well-formed": protocol G iswf(G) ✔ G = C → S. S → C.end deadlock-free G↾C = LC = LSG↾S S! S? C? C! LC = LS = : "views" of the protocol deadlock-free! [Honda et al., 2008] How to implement MPSTs in a programming language? Question
  13. 13. ③ LC ⊢ PC ? Go Thread State of the art: Deadlock freedom via code generation 13 ① wf(G) ? ② G↾C Global Protocol File Go Thread Go Thread In a MPST toolchain for programming language Go [D. Castro et al., POPL 2019]:
  14. 14. ③ LC ⊢ PC ? Go Thread State of the art: Deadlock freedom via code generation 14 ① wf(G) ? ② G↾C Global Protocol File Go Thread Go Thread In a MPST toolchain for programming language Go [D. Castro et al., POPL 2019]: deadlock-free (Well-formedness checking and End Point Projection) Go type (Generated code) Go type (Generated code) Go type (Generated code) Code generation ✔
  15. 15. ③ LC ⊢ PC ? Type checking by Go compiler ✔ (type checking to check protocol conformance) Go Thread State of the art: Deadlock freedom via code generation 15 ① wf(G) ? ② G↾C Global Protocol File Go Thread Go Thread In a MPST toolchain for programming language Go [D. Castro et al., POPL 2019]: deadlock-free (Well-formedness checking and End Point Projection) Go type (Generated code) Go type (Generated code) Go type (Generated code) Code generation ✔
  16. 16. ③ LC ⊢ PC ? Type checking by Go compiler ✔ (type checking to check protocol conformance) Go Thread State of the art: Deadlock freedom via code generation 16 ① wf(G) ? ② G↾C Global Protocol File Go Thread Go Thread In a MPST toolchain for programming language Go [D. Castro et al., POPL 2019]: deadlock-free (Well-formedness checking and End Point Projection) Go type (Generated code) Go type (Generated code) Go type (Generated code) Code generation ✔ deadlock-free
  17. 17. ③ LC ⊢ PC ? Type checking by Go compiler ✔ (type checking to check protocol conformance) Go Thread State of the art: Deadlock freedom via code generation 17 ① wf(G) ? ② G↾C Global Protocol File Go Thread Go Thread In a MPST toolchain for programming language Go [D. Castro et al., POPL 2019]: deadlock-free (Well-formedness checking and End Point Projection) Go type (Generated code) Go type (Generated code) Go type (Generated code) Code generation ✔ deadlock-free Is it possible to implement MPSTs without code generation? Question
  18. 18. ③ LC ⊢ PC ? ① wf(G) ? ② G↾C Global Protocol Combinator : Deadlock freedom solely by Types! 18 Yes (!) How?
  19. 19. ↓ A single OCaml program code file (.ml) OCaml Thread OCaml Thread OCaml Thread Protocol in OCaml ③ LC ⊢ PC ? ① wf(G) ? ② G↾C Global Protocol Combinator : Deadlock freedom solely by Types! 19 Yes (!) How?
  20. 20. ↓ A single OCaml program code file (.ml) OCaml Thread OCaml Thread OCaml Thread Protocol in OCaml ③ LC ⊢ PC ? ① wf(G) ? ② G↾C Global Protocol Combinator : Deadlock freedom solely by Types! 20 ✔ deadlock-free OCaml types OCaml types OCaml types Type checking & inference Yes (!) How?
  21. 21. ↓ A single OCaml program code file (.ml) OCaml Thread OCaml Thread OCaml Thread Protocol in OCaml ③ LC ⊢ PC ? ① wf(G) ? ② G↾C Global Protocol Combinator : Deadlock freedom solely by Types! 21 Type checking by OCaml compiler ✔ ✔ deadlock-free OCaml types OCaml types OCaml types Type checking & inference Yes (!) How?
  22. 22. ↓ A single OCaml program code file (.ml) OCaml Thread OCaml Thread OCaml Thread Protocol in OCaml ③ LC ⊢ PC ? ① wf(G) ? ② G↾C Global Protocol Combinator : Deadlock freedom solely by Types! 22 Type checking by OCaml compiler ✔ ✔ deadlock-free OCaml types OCaml types OCaml types Type checking & inference Yes (!) deadlock-free! How?
  23. 23. ↓ A single OCaml program code file (.ml) OCaml Thread OCaml Thread OCaml Thread Protocol in OCaml ③ LC ⊢ PC ? ① wf(G) ? ② G↾C Global Protocol Combinator : Deadlock freedom solely by Types! 23 Type checking by OCaml compiler ✔ ✔ deadlock-free OCaml types OCaml types OCaml types Type checking & inference Yes (!) deadlock-free! How? How/why do they work??
  24. 24. Global Combinators and well-formedness check 24 ① wf(G) ✔ let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) (r1 --> r2) lab : send a label lab from r1 to r2 (with possible payloads) Example: Simple OAuth protocol s c a
  25. 25. Global Combinators and well-formedness check 25 ① wf(G) ✔ let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) (r1 --> r2) lab : send a label lab from r1 to r2 (with possible payloads) Example: Simple OAuth protocol s c a
  26. 26. Global Combinators and well-formedness check 26 ① wf(G) ✔ let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) (r1 --> r2) lab : send a label lab from r1 to r2 (with possible payloads) Example: Simple OAuth protocol s c a
  27. 27. Global Combinators and well-formedness check 27 ① wf(G) ✔ let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) (r1 --> r2) lab : send a label lab from r1 to r2 (with possible payloads) Example: Simple OAuth protocol s c a let oauth_branch = choice_at s (to_c login_or_cancel) (s, (s --> c) login ((c --> a) password ((a --> c) auth finish))) (s, (s --> c) cancel ((c --> a) quit finish)) choice_at r g1 g2 : decide a protocol branching at r, between g1 and g2 Example: Adding a branch to Simple OAuth protocol (a few plumbings needed to convince the type checker) Each branch must begin from s
  28. 28. Global Combinators and well-formedness check 28 ① wf(G) ✔ let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) (r1 --> r2) lab : send a label lab from r1 to r2 (with possible payloads) Example: Simple OAuth protocol s c a let oauth_branch = choice_at s (to_c login_or_cancel) (s, (s --> c) login ((c --> a) password ((a --> c) auth finish))) (s, (s --> c) cancel ((c --> a) quit finish)) choice_at r g1 g2 : decide a protocol branching at r, between g1 and g2 NB: Branching in a protocol is a source of concurrency issues (a few plumbings needed to convince the type checker)
  29. 29. Global Combinators and well-formedness check 29 ① wf(G) ✔ let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) (r1 --> r2) lab : send a label lab from r1 to r2 (with possible payloads) Example: Simple OAuth protocol s c a let oauth_branch = choice_at s (to_c login_or_cancel) (s, (s --> c) login ((c --> a) password ((a --> c) auth finish))) (s, (s --> c) cancel ((c --> a) quit finish)) choice_at r g1 g2 : decide a protocol branching at r, between g1 and g2 NB: Branching in a protocol is a source of concurrency issues (a few plumbings needed to convince the type checker) Non-determinism/ Deadlock in a protocol a
  30. 30. Global Combinators and well-formedness check 30 ① wf(G) ✔ let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) (r1 --> r2) lab : send a label lab from r1 to r2 (with possible payloads) Example: Simple OAuth protocol s c a let oauth_branch = choice_at s (to_c login_or_cancel) (s, (s --> c) login ((c --> a) password ((a --> c) auth finish))) (s, (s --> c) cancel ((c --> a) quit finish)) choice_at r g1 g2 : decide a protocol branching at r, between g1 and g2 NB: Branching in a protocol is a source of concurrency issues (a few plumbings needed to convince the type checker) … is reported as a type error Non-determinism/ Deadlock in a protocol a
  31. 31. (Deadlock and type errors: An analysis) 31 let oauth_branch = choice_at s (to_c login_or_cancel) (s, (s --> c) login ((c --> a) password ((a --> c) auth finish))) (s, (s --> c) cancel ((c --> a) quit finish))a poke a instead of c The MPST theory rejects it: they are not "mergeable". Forming a "mixed choice" (which causes nondeterminism) c's first action is input from s c's first action is output to a
  32. 32. Deriving local types via type inference OCaml infers Local Types from global combinators. 32 ② G↾C let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) Example (again): Simple OAuth protocol s c a All local types are inferred at once, as a cons-list of structural types (here, s=0, c=1, a=2):
  33. 33. Deriving local types via type inference OCaml infers Local Types from global combinators. 33 ② G↾C let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) Example (again): Simple OAuth protocol s c a All local types are inferred at once, as a cons-list of structural types (here, s=0, c=1, a=2): val oauth : [ `cons of < role_C : < login : ('a * close) out lin > > * [ `cons of < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > * [ `cons of < role_C : [> `password of 'b * < role_C : < auth : ('c * close) out lin > > ] inp lin > * ([ `cons of close * 'x ] as 'x) ] ] ] Seq.t c!login s?login a!pass a?auth s!pass s?auth s c a
  34. 34. Deriving local types via type inference OCaml infers Local Types from global combinators. 34 ② G↾C let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) Example (again): Simple OAuth protocol s c a All local types are inferred at once, as a cons-list of structural types (here, s=0, c=1, a=2): val oauth : [ `cons of < role_C : < login : ('a * close) out lin > > * [ `cons of < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > * [ `cons of < role_C : [> `password of 'b * < role_C : < auth : ('c * close) out lin > > ] inp lin > * ([ `cons of close * 'x ] as 'x) ] ] ] Seq.t c!login s?login a!pass a?auth s!pass s?auth s c a Destination role's names are a method of an object < role_S < role_A < role_A
  35. 35. Deriving local types via type inference OCaml infers Local Types from global combinators. 35 ② G↾C let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) Example (again): Simple OAuth protocol s c a All local types are inferred at once, as a cons-list of structural types (here, s=0, c=1, a=2): val oauth : [ `cons of < role_C : < login : ('a * close) out lin > > * [ `cons of < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > * [ `cons of < role_C : [> `password of 'b * < role_C : < auth : ('c * close) out lin > > ] inp lin > * ([ `cons of close * 'x ] as 'x) ] ] ] Seq.t c!login s?login a!pass a?auth s!pass s?auth s c a Output labels are methods in an object < password Destination role's names are a method of an object < role_S < role_A < role_A
  36. 36. Deriving local types via type inference OCaml infers Local Types from global combinators. 36 ② G↾C let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) Example (again): Simple OAuth protocol s c a All local types are inferred at once, as a cons-list of structural types (here, s=0, c=1, a=2): val oauth : [ `cons of < role_C : < login : ('a * close) out lin > > * [ `cons of < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > * [ `cons of < role_C : [> `password of 'b * < role_C : < auth : ('c * close) out lin > > ] inp lin > * ([ `cons of close * 'x ] as 'x) ] ] ] Seq.t c!login s?login a!pass a?auth s!pass s?auth s c a Input labels are (polymorphic) variant type tags [ `login [ `auth Output labels are methods in an object < password Destination role's names are a method of an object < role_S < role_A < role_A
  37. 37. let ch = get_ch c oauth (* get a MPST channel for s *) val ch : < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > OCaml> let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) let thread_C () = match receive ch#role_S with | `login((u:string), ch)-> let ch = send ch#role_A#password "asdf" in match receive ch#role_A with | `auth((b:bool), ch) -> close ch Protocol conformance via OCaml's type checking 37 ③ LC ⊢ PC ✔
  38. 38. let ch = get_ch c oauth (* get a MPST channel for s *) val ch : < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > OCaml> let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) let thread_C () = match receive ch#role_S with | `login((u:string), ch)-> let ch = send ch#role_A#password "asdf" in match receive ch#role_A with | `auth((b:bool), ch) -> close ch Protocol conformance via OCaml's type checking 38 < role_S Select destination role via method invocation (#) role_S ③ LC ⊢ PC ✔
  39. 39. let ch = get_ch c oauth (* get a MPST channel for s *) val ch : < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > OCaml> let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) let thread_C () = match receive ch#role_S with | `login((u:string), ch)-> let ch = send ch#role_A#password "asdf" in match receive ch#role_A with | `auth((b:bool), ch) -> close ch Protocol conformance via OCaml's type checking 39 < role_S Select destination role via method invocation (#) role_S ③ LC ⊢ PC ✔ [ `login `login … and receive on it, then pattern-match the value against variant tags (labels) received payload
  40. 40. let ch = get_ch c oauth (* get a MPST channel for s *) val ch : < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > OCaml> let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) let thread_C () = match receive ch#role_S with | `login((u:string), ch)-> let ch = send ch#role_A#password "asdf" in match receive ch#role_A with | `auth((b:bool), ch) -> close ch Protocol conformance via OCaml's type checking 40 < role_S Select destination role via method invocation (#) role_S ③ LC ⊢ PC ✔ [ `login `login … and receive on it, then pattern-match the value against variant tags (labels) received payload "Next" channel is supplied as a part of the returned value
  41. 41. let ch = get_ch c oauth (* get a MPST channel for s *) val ch : < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > OCaml> let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) let thread_C () = match receive ch#role_S with | `login((u:string), ch)-> let ch = send ch#role_A#password "asdf" in match receive ch#role_A with | `auth((b:bool), ch) -> close ch Protocol conformance via OCaml's type checking 41 < role_S Select destination role via method invocation (#) role_S < role_A role_A ③ LC ⊢ PC ✔ [ `login `login … and receive on it, then pattern-match the value against variant tags (labels) received payload "Next" channel is supplied as a part of the returned value
  42. 42. let ch = get_ch c oauth (* get a MPST channel for s *) val ch : < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > OCaml> let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) let thread_C () = match receive ch#role_S with | `login((u:string), ch)-> let ch = send ch#role_A#password "asdf" in match receive ch#role_A with | `auth((b:bool), ch) -> close ch Protocol conformance via OCaml's type checking 42 < role_S Select destination role via method invocation (#) role_S < role_A role_A ③ LC ⊢ PC ✔ [ `login `login … and receive on it, then pattern-match the value against variant tags (labels) received payload "Next" channel is supplied as a part of the returned value < password #password Select an output label via method invocation (#), then send it with a payload
  43. 43. let ch = get_ch c oauth (* get a MPST channel for s *) val ch : < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > OCaml> let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) let thread_C () = match receive ch#role_S with | `login((u:string), ch)-> let ch = send ch#role_A#password "asdf" in match receive ch#role_A with | `auth((b:bool), ch) -> close ch Protocol conformance via OCaml's type checking 43 < role_S Select destination role via method invocation (#) role_S < role_A role_A role_A < role_A ③ LC ⊢ PC ✔ [ `login `login … and receive on it, then pattern-match the value against variant tags (labels) received payload "Next" channel is supplied as a part of the returned value < password #password Select an output label via method invocation (#), then send it with a payload
  44. 44. let ch = get_ch c oauth (* get a MPST channel for s *) val ch : < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > OCaml> let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) let thread_C () = match receive ch#role_S with | `login((u:string), ch)-> let ch = send ch#role_A#password "asdf" in match receive ch#role_A with | `auth((b:bool), ch) -> close ch Protocol conformance via OCaml's type checking 44 < role_S Select destination role via method invocation (#) role_S < role_A role_A `auth [ `auth role_A < role_A ③ LC ⊢ PC ✔ [ `login `login … and receive on it, then pattern-match the value against variant tags (labels) received payload "Next" channel is supplied as a part of the returned value < password #password Select an output label via method invocation (#), then send it with a payload
  45. 45. let ch = get_ch s oauth (* get a MPST channel for s *) val ch : < role_S : [> `login of 'a * < role_A : < password : ('b * < role_A : [> `auth of 'c * close ] inp lin >) out lin > > ] inp lin > OCaml> let oauth = (s --> c) login ((c --> a) password ((a --> c) auth finish)) let thread_C () = match receive ch#role_S with | `login((u:string), ch)-> let ch = send ch#role_A#password "asdf" in match receive ch#role_A with | `auth((b:bool), ch) -> close ch 45 Protocol conformance via OCaml's type checking③ LC ⊢ PC ✔ ro If there is a typo … OCaml reports a type error at this point
  46. 46. ↓ A single OCaml Source code file (.ml) OCaml Program OCaml Program OCaml Program Protocol in OCaml ③ LC ⊢ PC ? ① wf(G) ? ② G↾C Global Protocol Combinator : Deadlock freedom by Types! 46 Type checking by OCaml compiler ✔ ✔ deadlock-free OCaml types OCaml types OCaml types Type checking & inference Recap deadlock-free!
  47. 47. ↓ A single OCaml Source code file (.ml) OCaml Program OCaml Program OCaml Program Protocol in OCaml ③ LC ⊢ PC ? ① wf(G) ? ② G↾C Global Protocol Combinator : Deadlock freedom by Types! 47 Type checking by OCaml compiler ✔ ✔ deadlock-free OCaml types OCaml types OCaml types Type checking & inference Recap deadlock-free! Are they really correct??
  48. 48. GPC: Are they correct 48 A. Key idea: Global Combinators pre-generate channels ❖ Multiparty channels as nested sequence of simply-typed channels B. Formalisation of GPC with Deadlock-freedom Theorem ❖ OCamlM: A minimal concurrent language ❖ Typing rules for Global Combinators C. Implementation: GPC as a typed DSL in OCaml ❖ Based on a set of type manipulation techniques (GADTs, field label encoding, and plumbings such as polymorphic record extension) GPC key ingredients
  49. 49. GPC: Are they correct 49 A. Key idea: Global Combinators pre-generate channels ❖ Multiparty channels as nested sequence of simply-typed channels B. Formalisation of GPC with Deadlock-freedom Theorem ❖ OCamlM: A minimal concurrent language ❖ Typing rules for Global Combinators C. Implementation: GPC as a typed DSL in OCaml ❖ Based on a set of type manipulation techniques (GADTs, label encoding, and plumbings such as polymorphic record extension) GPC key ingredients
  50. 50. 50 Let's start cooking!! A. Key idea: Global Combinators pre-generate channels
  51. 51. A. Key idea: Global Combinators pre-generate channels 51 S C A ⟨⟩ ⟨⟩ ⟨⟩ let oAuth = finish
  52. 52. A. Key idea: Global Combinators pre-generate channels 52 S C A Sauth ⟨?Sauth⟩ ⟨!Sauth⟩ ⟨⟩ let oAuth = (A → C) auth finish
  53. 53. A. Key idea: Global Combinators pre-generate channels 53 let oAuth = (C → A) password ((A → C) auth finish) S C A Sauth Spasswd ⟨!Spasswd; ?Sauth⟩ ⟨?Spasswd; !Sauth⟩ ⟨⟩
  54. 54. A. Key idea: Global Combinators pre-generate channels 54 let oAuth = (S → C) login ((C → A) password ((A → C) auth finish)) S C A ⟨?Slogin ; !Spasswd; ?Sauth.0 ⟩ ⟨?Spasswd; !Sauth⟩ Sauth Spasswd Slogin ⟨!Slogin ⟩
  55. 55. A. Key idea: Global Combinators pre-generate channels 55 let oAuth = (S → C) login ((C → A) password ((A → C) auth finish)) S C A ⟨?Slogin ; !Spasswd; ?Sauth.0 ⟩ ⟨?Spasswd; !Sauth⟩ Sauth Spasswd Slogin ⟨!Slogin ⟩
  56. 56. Distribute them and start the communication 56 PS PC PA !Slogin.0| ?Slogin ; !Spasswd; ?Sauth.0| ?Spasswd;!Sauth.0
  57. 57. Distribute them and start the communication 57 PS PC PA 0| !Spasswd; ?Sauth.0| ?Spasswd;!Sauth.0
  58. 58. Distribute them and start the communication 58 PS PC PA 0| ?Sauth.0| !Sauth.0
  59. 59. Distribute them and start the communication 59 PS PC PA 0| 0| 0
  60. 60. Distribute them and start the communication 60 PS PC PA !Slogin.0| ?Slogin ; !Spasswd; ?Sauth.0| ?Spasswd;!Sauth.0 ❖ All these channels are simply-typed (hence no type-errors) ❖ Global combinators aim to be deadlock-free ❖ The nested structure enforces usage order Point
  61. 61. GPC: Are they correct? (cont.) 61 A. Key idea: Global Combinators pre-generate channels ❖ Multiparty channels as nested sequence of simply-typed channels B. Formalisation of GPC (with Deadlock-freedom Theorem) ❖ OCamlM: A minimal concurrent language ❖ Typing rules for Global Combinators (with hints to OCaml DSL) ❖ Session Type merging C. Implementation: GPC as a typed DSL in OCaml ❖ Based on a set of type manipulation techniques (GADTs, field label encoding, and plumbings such as polymorphic record extension) GPC key ingredients
  62. 62. B. OCamlM: Formalisation of GPC with Deadlock-freedom Theorem • A minimal concurrent language with structural subtyping, equi-recursive types and simply-typed channels • Typing rules for global combinators 62
  63. 63. Typing rules 63 p1 pn … … … Point: give an index for each role (and order roles) wf(G) ✔, G↾C
  64. 64. The typing rule for (-->) 64 p1 pn … pi pj … … wf(G) ✔, G↾C i
  65. 65. The typing rule for (-->) 65 p1 pn … pi pj … … Index-based type update wf(G) ✔, G↾C i
  66. 66. The typing rule for (-->) 66 p1 pn … pi pj … … Index-based type update p1 pn … pi pj … … "Wrap" with opponent's role names and labels wf(G) ✔, G↾C i
  67. 67. The typing rule for (-->) 67 p1 pn … pi pj … … Index-based type update p1 pn … pi pj … … "Wrap" with opponent's role names and labels Implement them by using GADTs and polymorphic lens (explained later) available in OCaml wf(G) ✔, G↾C i
  68. 68. The typing rule for (-->) 68 p1 pn … pi pj … … Index-based type update p1 pn … pi pj … … "Wrap" with opponent's role names and labels Requires first-class record fields (methods) and variant tags ⇒ Encode them as values encode it in OCaml Implement them by using GADTs and polymorphic lens (explained later) available in OCaml wf(G) ✔, G↾C i
  69. 69. The typing rule for branching (choice_at) 69 wf(G) ✔, G↾C
  70. 70. The typing rule for branching (choice_at) 70 Ensure that pa is a sending wf(G) ✔, G↾C
  71. 71. The typing rule for branching (choice_at) 71 Ensure that pa is a sending Output labels must be disjoint (deterministic) wf(G) ✔, G↾C
  72. 72. The typing rule for branching (choice_at) 72 Ensure that pa is a sending Output labels must be disjoint (deterministic) Merge two records (objects) into one wf(G) ✔, G↾C
  73. 73. The typing rule for branching (choice_at) 73 Ensure that pa is a sending Output labels must be disjoint (deterministic) Merge two records (objects) into one Encode disjoint record merging encode it in OCaml wf(G) ✔, G↾C
  74. 74. The typing rule for branching (choice_at) 74 wf(G) ✔, G↾C Too restrictive for communication protocols Solution: Subtyping! Requires each role having the same type (behaviour) in each branch → seems standard wrt. if-then-else construct, but
  75. 75. The typing rule for branching (choice_at) 75 wf(G) ✔, G↾C Too restrictive for communication protocols Solution: Subtyping! Row polymorphism (objects and polymorphic variants) available in OCaml Requires each role having the same type (behaviour) in each branch → seems standard wrt. if-then-else construct, but
  76. 76. Typing rules 76 … p1 pn … pi … p1 pn … pi … p1 pn … pi … Γ ⊢ choice … {g1; g2} : ⋯×p&{m1:T1, m2:T2}×⋯ Γ ⊢ g1 : ⋯×p&{m1:T1}×⋯ Γ ⊢ g2 : ⋯×p&{m2:T2}×⋯ Desired type (According to Full Merging in MPST) A problem: p&{m1:T1} ≠ p&{m2:T2}
  77. 77. Typing rules 77 … p1 pn … pi … p1 pn … pi … p1 pn … pi … Γ ⊢ choice … {m1:g1; m2:g2} : ⋯×p&{m1:T1, m2:T2}×⋯ Γ ⊢ g1 : ⋯×p&{m1:T1}×⋯ Γ ⊢ g1 : ⋯×p&{m2:T2}×⋯ ? ?
  78. 78. Typing rules 78 … p1 pn … pi … p1 pn … pi … p1 pn … pi … Γ ⊢ g1 : ⋯×p&{m1:T1, m2:T2}×⋯ Γ ⊢ g2 : ⋯×p&{m1:T1, m2:T2}×⋯ Γ ⊢ g1 : ⋯×p&{m1:T1}×⋯ Γ ⊢ g1 : ⋯×p&{m2:T2}×⋯ Γ ⊢ choice … {g1; g2} : ⋯×p&{m1:T1, m2:T2}×⋯ p&{m1:T1} ≤ p&{m1:T1; m2:T2} p&{m2:T2} ≤ p&{m1:T1; m2:T2} Subtyping!!
  79. 79. Deadlock and type errors: An analysis 79 let oauth_branch = choice_at s (to_c login_or_cancel) (s, (s --> c) login ((c --> a) password ((a --> c) auth finish))) (s, (s --> c) cancel ((c --> a) quit finish))a poke a instead of c The MPST theory rejects it: they are not "mergeable". Forming a "mixed choice" (which causes nondeterminism)
  80. 80. Deadlock and type errors: An analysis 80 let oauth_branch = choice_at s (to_c login_or_cancel) (s, (s --> c) login ((c --> a) password ((a --> c) auth finish))) (s, (s --> c) cancel ((c --> a) quit finish))a poke a instead of c The MPST theory rejects it: they are not "mergeable". Forming a "mixed choice" (which causes nondeterminism) c's first action is output to a <a: <quit: !bool*cont2>>
  81. 81. Deadlock and type errors: An analysis 81 let oauth_branch = choice_at s (to_c login_or_cancel) (s, (s --> c) login ((c --> a) password ((a --> c) auth finish))) (s, (s --> c) cancel ((c --> a) quit finish))a poke a instead of c The MPST theory rejects it: they are not "mergeable". Forming a "mixed choice" (which causes nondeterminism) c's first action is input from s <s: ?[login_str*cont1]> c's first action is output to a <a: <quit: !bool*cont2>>
  82. 82. Deadlock and type errors: An analysis 82 let oauth_branch = choice_at s (to_c login_or_cancel) (s, (s --> c) login ((c --> a) password ((a --> c) auth finish))) (s, (s --> c) cancel ((c --> a) quit finish))a poke a instead of c The MPST theory rejects it: they are not "mergeable". Forming a "mixed choice" (which causes nondeterminism) c's first action is input from s <s: ?[login_str*cont1]> c's first action is output to a <a: <quit: !bool*cont2>> No least upper bound (common supertype) ⇒ type error No least upper bound (common supertype) ⇒ type error
  83. 83. A note on typing 83 <r: ?[lab: T1*T2]> <r: <lab: !T1*T2>> Input and output session types are not symmetric with each other. Why? sok : ?bool, scancel : ?int : ?[ok_(boolו); cancel_(int× …)] (← wanted) Making a multiplexed channel from simply-typed channels
  84. 84. A note on typing 84 <r: ?[lab: T1*T2]> <r: <lab: !T1*T2>> Input and output session types are not symmetric with each other. Why? sok : ?bool, scancel : ?int : ?[ok_(boolו); cancel_(int× …)] (← wanted) choose : List[?T] -> ?T makes a (multiplexed) channel (external choice) wrap : (α -> β) -> ?α -> ?β makes a wrapped channel Concurrent ML (Reppy, 1993) Types are slightly modified, they uses "events" in reality Making a multiplexed channel from simply-typed channels
  85. 85. A note on typing 85 <r: ?[lab: T1*T2]> <r: <lab: !T1*T2>> Input and output session types are not symmetric with each other. Why? sok : ?bool, scancel : ?int wrap (λx.[ok=(x,•)]) sok : ?[ok_(boolו)] wrap (λx.[cancel=(x,…)]) scancel : ?[cancel_(int×…)] : ?[ok_(boolו); cancel_(int× …)] (← wanted) choose : List[?T] -> ?T makes a (multiplexed) channel (external choice) wrap : (α -> β) -> ?α -> ?β makes a wrapped channel Concurrent ML (Reppy, 1993) Types are slightly modified, they uses "events" in reality Making a multiplexed channel from simply-typed channels
  86. 86. A note on typing 86 <r: ?[lab: T1*T2]> <r: <lab: !T1*T2>> Input and output session types are not symmetric with each other. Why? sok : ?bool, scancel : ?int wrap (λx.[ok=(x,•)]) sok : ?[ok_(boolו)] wrap (λx.[cancel=(x,…)]) scancel : ?[cancel_(int×…)] List(wrap (λx.[ok=(x,•)]) sok; wrap (λx.[cancel=(x,…)]) scancel) : List[ ?[ok_(boolו), cancel_(int×…)] ] : ?[ok_(boolו); cancel_(int× …)] (← wanted) choose : List[?T] -> ?T makes a (multiplexed) channel (external choice) wrap : (α -> β) -> ?α -> ?β makes a wrapped channel Concurrent ML (Reppy, 1993) Types are slightly modified, they uses "events" in reality Making a multiplexed channel from simply-typed channels
  87. 87. A note on typing 87 <r: ?[lab: T1*T2]> <r: <lab: !T1*T2>> Input and output session types are not symmetric with each other. Why? sok : ?bool, scancel : ?int wrap (λx.[ok=(x,•)]) sok : ?[ok_(boolו)] wrap (λx.[cancel=(x,…)]) scancel : ?[cancel_(int×…)] List(wrap (λx.[ok=(x,•)]) sok; wrap (λx.[cancel=(x,…)]) scancel) : List[ ?[ok_(boolו), cancel_(int×…)] ] choose (List(wrap (λx.[ok=(x,•)]) sok; wrap (λx.[cancel=(x,…)]) scancel)) : ?[ok_(boolו); cancel_(int× …)] (← wanted) choose : List[?T] -> ?T makes a (multiplexed) channel (external choice) wrap : (α -> β) -> ?α -> ?β makes a wrapped channel Concurrent ML (Reppy, 1993) Types are slightly modified, they uses "events" in reality Making a multiplexed channel from simply-typed channels
  88. 88. GPC: Are they correct? (cont.) 88 A. Key idea: Global Combinators pre-generate channels ❖ Multiparty channels as nested sequence of simply-typed channels B. Formalisation of GPC (with Deadlock-freedom Theorem) ❖ OCamlM: A minimal concurrent language ❖ Typing rules for Global Combinators (with hints to OCaml DSL) ❖ Session Type merging C. Implementation: GPC as a typed DSL in OCaml ❖ Based on a set of type manipulation techniques (GADTs, field label encoding, and details of plumbings for polymorphic record extension) ❖ Benchmarks: Garbage collection matters ❖ Linearity monad GPC key ingredients Please ask me over beer!
  89. 89. GPC wrap up 89 Global Protocol Combinator: a DSL for writing global protocols ❖ Key Ingredients: Global Combinators ❖ Covers all basic MPST features (including full merging) ❖ Extensions: HTTP, and OAuth Example (on top of it), and more OCamlM: fomalisation of a minimal programming language for GPC ❖ Subject Reduction, Operational Correspondence and Deadlock-freedom ❖ Types for global combinators ❖ Merging is a least upper bound in subtyping relation Sauth Spasswd let oauth = (s --> c) login … p1 pn … … …
  90. 90. Future Work 90 A → B B → C A → B • Deadlock-freedom proof on full global combinators ❖ Including more expressive ones (e.g. relaxed loop conditions) ❖ Scatter/Gather (broadcast), undirected internal choice, … • Implementation in other programming languages ❖ TypeScript (structural subtyping from beginning, and will have recursive types as well) ❖ Haskell (automatically construct global combinators via type classes) Thank you!
  91. 91. Extra slides 91
  92. 92. Loops are easy (for now) 92 let oAuth = (S → C) login ((C → A) password ((A → C) auth finish)) S C A ⟨?Slogin ; !Spasswd; ?Sauth.0 ⟩ ⟨?Spasswd; !Sauth⟩ Sauth Spasswd Slogin ⟨?Slogin ⟩
  93. 93. Loops are easy (for now) 93 let oAuth = fix (λx. (S → C) login ((C → A) password ((A → C) auth x)) S C A μx.⟨?Slogin ; !Spasswd; ?Sauth; x ⟩ μx. ⟨?Spasswd; !Sauth; x⟩ Sauth Spasswd Slogin μx. ⟨?Slogin; x⟩
  94. 94. Branchings? 94 S C A Sauth Spasswd Slogin (S → C) login ((C → A) password ((A → C) auth finish)) (S → C) cancel ((C → A) quit finish) S C A Squit Scancel +?
  95. 95. Input / output primitives and row-polymorphism in OCaml 95 let thread_A () = let `password((p:string), ch) = receive ch#role_C in let ch = send ch#role_C#auth true in close ch (FP's type inference-friendly structural typing)
  96. 96. Input / output primitives and row-polymorphism in OCaml 96 let thread_A () = let `password((p:string), ch) = receive ch#role_C in let ch = send ch#role_C#auth true in close ch (FP's type inference-friendly structural typing) Input labels are polymorphic variants Input labels are polymorphic variants
  97. 97. Input / output primitives and row-polymorphism in OCaml 97 let thread_A () = let `password((p:string), ch) = receive ch#role_C in let ch = send ch#role_C#auth true in close ch (FP's type inference-friendly structural typing) Input labels are polymorphic variants Input labels are polymorphic variants Output labels are methods in an object (fields in a polymorphic record) Output labels are methods in an object (fields in a polymorphic record)
  98. 98. Input / output primitives and row-polymorphism in OCaml 98 let thread_A () = let `password((p:string), ch) = receive ch#role_C in let ch = send ch#role_C#auth true in close ch OCaml's row-polymorphism simulates session-type subtyping (FP's type inference-friendly structural typing) Input labels are polymorphic variants Input labels are polymorphic variants Output labels are methods in an object (fields in a polymorphic record) Output labels are methods in an object (fields in a polymorphic record)
  99. 99. Input / output primitives and row-polymorphism in OCaml 99 let thread_A () = let `password((p:string), ch) = receive ch#role_C in let ch = send ch#role_C#auth true in close ch OCaml's row-polymorphism simulates session-type subtyping (FP's type inference-friendly structural typing) Input labels are polymorphic variants Input labels are polymorphic variants Output labels are methods in an object (fields in a polymorphic record) Output labels are methods in an object (fields in a polymorphic record) val ch : < role_C : [< `password of string * < role_C : < auth : (bool * close) out lin; .. >; .. > ] inp lin; .. > -> unit
  100. 100. Input / output primitives and row-polymorphism in OCaml 100 let thread_A () = let `password((p:string), ch) = receive ch#role_C in let ch = send ch#role_C#auth true in close ch OCaml's row-polymorphism simulates session-type subtyping (FP's type inference-friendly structural typing) Input labels are polymorphic variants Input labels are polymorphic variants Output labels are methods in an object (fields in a polymorphic record) Output labels are methods in an object (fields in a polymorphic record) val ch : < role_C : [< `password of string * < role_C : < auth : (bool * close) out lin; .. >; .. > ] inp lin; .. > -> unit Inferred polymorphic variant type: it can have less receiving labels (= in this case it must have password at least since there must be one)
  101. 101. Input / output primitives and row-polymorphism in OCaml 101 let thread_A () = let `password((p:string), ch) = receive ch#role_C in let ch = send ch#role_C#auth true in close ch OCaml's row-polymorphism simulates session-type subtyping (FP's type inference-friendly structural typing) Input labels are polymorphic variants Input labels are polymorphic variants Output labels are methods in an object (fields in a polymorphic record) Output labels are methods in an object (fields in a polymorphic record) val ch : < role_C : [< `password of string * < role_C : < auth : (bool * close) out lin; .. >; .. > ] inp lin; .. > -> unit Inferred polymorphic variant type: it can have less receiving labels (= in this case it must have password at least since there must be one) Inferred object type: it can have more sending labels
  102. 102. Branching 102 let oauth1 = choice_at s (to_c login_or_cancel) (s, (s --> c) login @@ (c --> a) password @@ (a --> c) auth finish) (s, (s --> c) cancel @@ (c --> a) quit finish) A protocol with branching: let thread_C () = match receive ch#role_S with | `cancel((code:int), ch) -> close (send chc#role_A#quit ()) | `login((), ch) -> let ch = send ch#role_A#password "asdf" in let `auth(b, ch) = receive ch#role_A in close ch Code for C (waiting for S with an external choice):
  103. 103. Branching 103 let oauth1 = choice_at s (to_c login_or_cancel) (s, (s --> c) login @@ (c --> a) password @@ (a --> c) auth finish) (s, (s --> c) cancel @@ (c --> a) quit finish) A protocol with branching: S will decide a branch, then C and A will follow let thread_C () = match receive ch#role_S with | `cancel((code:int), ch) -> close (send chc#role_A#quit ()) | `login((), ch) -> let ch = send ch#role_A#password "asdf" in let `auth(b, ch) = receive ch#role_A in close ch Code for C (waiting for S with an external choice):
  104. 104. Branching 104 let oauth1 = choice_at s (to_c login_or_cancel) (s, (s --> c) login @@ (c --> a) password @@ (a --> c) auth finish) (s, (s --> c) cancel @@ (c --> a) quit finish) A protocol with branching: S will decide a branch, then C and A will follow let thread_C () = match receive ch#role_S with | `cancel((code:int), ch) -> close (send chc#role_A#quit ()) | `login((), ch) -> let ch = send ch#role_A#password "asdf" in let `auth(b, ch) = receive ch#role_A in close ch Code for C (waiting for S with an external choice):An external choice is a pattern matching (idiomatic OCaml)
  105. 105. Loops and delegations (1) 105 let oauth2 = fix (fun self -> choice_at s (to_c login_cancel_or_retry) (s, oauth1 ()) (s, (s --> c) retry @@ (c --> a) retry self)) Thanks to OCaml's equi-recursive types (built in polymorphic variants and objects by default), programmers can handle recursions very naturally:
  106. 106. Loops and delegations (1) 106 let oauth2 = fix (fun self -> choice_at s (to_c login_cancel_or_retry) (s, oauth1 ()) (s, (s --> c) retry @@ (c --> a) retry self)) recursionrecursion Thanks to OCaml's equi-recursive types (built in polymorphic variants and objects by default), programmers can handle recursions very naturally:
  107. 107. Loops and delegations (1) 107 let oauth2 = fix (fun self -> choice_at s (to_c login_cancel_or_retry) (s, oauth1 ()) (s, (s --> c) retry @@ (c --> a) retry self)) recursionrecursion protocol reuse Thanks to OCaml's equi-recursive types (built in polymorphic variants and objects by default), programmers can handle recursions very naturally:
  108. 108. Loops and delegations (1) 108 let oauth2 = fix (fun self -> choice_at s (to_c login_cancel_or_retry) (s, oauth1 ()) (s, (s --> c) retry @@ (c --> a) retry self)) recursionrecursion protocol reuse val ch_S : < role_C : < cancel : ('_b * close) out lin; login : ('_c * close) out lin; retry : ('_d * 'a) out lin > > as 'a OCaml> Thanks to OCaml's equi-recursive types (built in polymorphic variants and objects by default), programmers can handle recursions very naturally:
  109. 109. Loops and delegations (1) 109 let oauth2 = fix (fun self -> choice_at s (to_c login_cancel_or_retry) (s, oauth1 ()) (s, (s --> c) retry @@ (c --> a) retry self)) recursionrecursion protocol reuse val ch_S : < role_C : < cancel : ('_b * close) out lin; login : ('_c * close) out lin; retry : ('_d * 'a) out lin > > as 'a OCaml> recursionrecursion Thanks to OCaml's equi-recursive types (built in polymorphic variants and objects by default), programmers can handle recursions very naturally:
  110. 110. Loops and delegations (2) 110 let oauth_deleg = (mst --> wrk) (msg >: get_prot s oauth2) finish Delegation doesn't need any special treatment, since OCaml will just infer the delegated type. However, you can annotate labels with a delegated protocol, like this: val ch_Mst : < role_Wrk : < msg : (< role_C : < cancel : ('_b * close) out lin; login : ('_c * close) out lin; retry : ('_d * 'a) out lin > > as 'a * close) out lin > > OCaml> Delegated type
  111. 111. Detecting protocol errors using types 111 Non-determinism/ Deadlock in a protocol let oauth1 = choice_at s (to_c login_or_cancel) (s, (s --> c) login @@ (c --> a) password @@ (a --> c) auth finish) (s, (s --> a) cancel @@ (c --> a) quit finish) NB: Branching is a source of concurrency issues
  112. 112. Detecting protocol errors using types 112 Non-determinism/ Deadlock in a protocol let oauth1 = choice_at s (to_c login_or_cancel) (s, (s --> c) login @@ (c --> a) password @@ (a --> c) auth finish) (s, (s --> a) cancel @@ (c --> a) quit finish) … is also reported as a type error NB: Branching is a source of concurrency issues
  113. 113. Detecting protocol errors using types 113 Non-determinism/ Deadlock in a protocol let oauth1 = choice_at s (to_c login_or_cancel) (s, (s --> c) login @@ (c --> a) password @@ (a --> c) auth finish) (s, (s --> a) cancel @@ (c --> a) quit finish) … is also reported as a type error Theorem: if a global type G is well-formed, its encoding to a global combinator g =⟦G⟧ is well-typed in OCamlM. NB: Branching is a source of concurrency issues
  114. 114. Detecting protocol errors using types 114 Non-determinism/ Deadlock in a protocol let oauth1 = choice_at s (to_c login_or_cancel) (s, (s --> c) login @@ (c --> a) password @@ (a --> c) auth finish) (s, (s --> a) cancel @@ (c --> a) quit finish) … is also reported as a type error Theorem: if a global type G is well-formed, its encoding to a global combinator g =⟦G⟧ is well-typed in OCamlM. NB: Branching is a source of concurrency issues Global Combinators have full expressivity of MPST Global Types
  115. 115. [Formalisation] OCamlM : a Minimal calculus for global combinators Main results: 115 A calculus with structural subtyping, equi-recursive types and i/o-typed channels Theorem (Subject Reduction): if ⊢ e and e→* e' then ⊢ e' Theorem (Operational Correspondence): (Completeness) (Soundness) Corollary (Deadlock Freedom): If an MPST process P is deadlock-free, OCamlM expression e=⟦P⟧ is deadlock-free.
  116. 116. Other features and Examples ✔ Branchings, loops, delegations ❖ Allows full merging in a branching (next slide) ✔ MPST as a wrapper ❖ Offers global protocol on top of HTTP, DNS, … ❖ Example: OAuth, DNS server, SMTP client, … ❖ Utilise concurrent/distributed libraries: Lwt (lightweight threads) and Unix IPC ✔ More Extensions ❖ Scatter/Gather (broadcast) ❖ Undirected choice (-nolive) ❖ Unbalanced Loops 116 B⊕m1 C⊕m2 B⊕m1C⊕m2 A → B B → C A → B
  117. 117. Full merging 117 let oauth1 = choice_at s (to_c login_or_cancel) (s, (s --> c) login @@ (c --> a) password @@ (a --> c) auth finish) (s, (s --> c) cancel @@ (c --> a) quit finish) Input labels are polymorphic variantsA can have different input branches Example: A branch happens between S and C. ⇒ Merge A's two behaviours into one Merging strategy Synopsis Implementations Plain merging All branches must have same labels/continuation (restrictive) Scalas et al. (ECOOP 2017) ✔ Full merging Different input labels/continuations can be mergeable (more relaxed) This work
  118. 118. • Benchmarks reflect our design decision to use mutable long lived objects (e.g channel vectors) ❖ Our work: few mutable long lived objects, created at the start of the protocol ❖ State-of-the-art (linear-decomposition [Scala et.a]): many small channels, created on-demand (during the protocol execution) 118
  119. 119. Benchmarks • Comparison with Linear (Binary) Decomposition [Scalas et al., 2017] ❖ Translation from MPST to Linear Types ❖ Continuation Passing Style (CPS): It creates (and exchanges) a fresh channel at each communication step ❖ Must be slower than us?? • Compete with ours in some cases (!), but CPS is slower in general ❖ OCaml's major GC is doing nice work • Monad (static linearity checking with overhead) VS. Direct style (dynamic) 119
  120. 120. Put All Slides in right contexts!! • Most surprising parts: • (what is it) 簡単に? programmers can write like this… select opponent role by method, then (a) send by method / (b) receive it and pattern match on variants. Errors are detected like this… GC well-formedness errors and Local type conformance errors. Bonus: recursive sessions, session subtyping and delegations are all free. • (why/how gc-like typing is possible??) (1) (why EPP is possible, it is operation on types!!: see onion and --> typing.) (2) (why well-formedness checking is possible? What is well-formedness?: see typing rules) • (key idea) タマネギ.2枚くらいにおさめる • (how it is typed) --> typing and implementation (mention that OCaml do not have such first-class?) • (how deadlock is detected: harder) choice, nondeterminisim and deadlock choice is like an if-then-else. Two branches are merged into one. (Sub)typing and global combinator typing prevents occasional wrong branching. • (how it is imlpemented) lenses and first class record fields • Choice_at typing and record extensions ❖ Least upper bound is merging ❖ We have more expressive GTs ❖ Subtyping and equi-recursive types ❖ Unguardedness and Unbalanced merging • Linearity monad • Deadlock freeness, syntax of local types, and undirected choice (sending and receiving) • Benchmarks • Meaning of type errors and relationship to deadlocks ❖ Mergeability and local type syntax ❖ Possibility to extension (i.e. non-directed merging) ❖ Why roles are record fields – what if it was variant tags 120
  121. 121. Channel Vectors: Inhabiting MPSTs as simple channel types 121 TA = B⊕{ok.•; cancel.B&cancel.•} TB = A&{ok.•; cancel.B⊕cancel.•}
  122. 122. Channel Vectors: Inhabiting MPSTs as simple channel types 122 sok scancel1 scancel2 sok scancel1 scancel2 Idea: Put simply-typed channels in a tree-like data structure TA = B⊕{ok.•; cancel.B&cancel.•} TB = A&{ok.•; cancel.B⊕cancel.•}
  123. 123. Internal Choice is Record A record having pairs of an output channel and "the rest" in its fields 123 ⟦ B⊕{ok.•; cancel.B&cancel(int).•} ⟧s = <B = <ok= (sok, •); cancel= (scancel1, ⟦...⟧s)> > Pictorially:
  124. 124. Internal Choice is Record A record having pairs of an output channel and "the rest" in its fields 124 ⟦ B⊕{ok.•; cancel.B&cancel(int).•} ⟧s = <B = <ok= (sok, •); cancel= (scancel1, ⟦...⟧s)> > (scancel, )(sok, ) … ok cancel Pictorially:
  125. 125. Internal Choice is Record A record having pairs of an output channel and "the rest" in its fields 125 ⟦ B⊕{ok.•; cancel.B&cancel(int).•} ⟧s = : ⟨B : ⟨ok: !(int*int)ו; cancel: !(bool) ×⟦…⟧⟩ ⟩ Provided that • sok : Och, scancel : Och (! is an output channel type) <B = <ok= (sok, •); cancel= (scancel1, ⟦...⟧s)> > (scancel, )(sok, ) … ok cancel Pictorially:
  126. 126. External choice is variant input 126 Variant input type: ?[ok_(boolו); cancel_(int× …)] Variant type: [ok_(boolו); cancel_(int× …)] ("Either ok (with boolו) or cancel (with int×…)") ("Receives either ok (with boolו) or cancel (with int×…)") cancel(_, )ok(_, ) scancel1sok cancel external choice Pictorially: But how?
  127. 127. A Solution from Concurrent ML (Reppy, 1993) 127 … has a set of (event) primitives we need! choose : List[?T] -> ?T makes a (multiplexed) channel (external choice) wrap : (α -> β) -> ?α -> ?β makes a wrapped channel sok : ?bool, scancel : ?int : ?[ok_(boolו); cancel_(int× …)] (← wanted)
  128. 128. A Solution from Concurrent ML (Reppy, 1993) 128 … has a set of (event) primitives we need! choose : List[?T] -> ?T makes a (multiplexed) channel (external choice) wrap : (α -> β) -> ?α -> ?β makes a wrapped channel sok : ?bool, scancel : ?int wrap (λx.[ok=(x,•)]) sok : ?[ok_(boolו)] wrap (λx.[cancel=(x,…)]) scancel : ?[cancel_(int×…)] : ?[ok_(boolו); cancel_(int× …)] (← wanted)
  129. 129. A Solution from Concurrent ML (Reppy, 1993) 129 … has a set of (event) primitives we need! choose : List[?T] -> ?T makes a (multiplexed) channel (external choice) wrap : (α -> β) -> ?α -> ?β makes a wrapped channel sok : ?bool, scancel : ?int wrap (λx.[ok=(x,•)]) sok : ?[ok_(boolו)] wrap (λx.[cancel=(x,…)]) scancel : ?[cancel_(int×…)] List(wrap (λx.[ok=(x,•)]) sok; wrap (λx.[cancel=(x,…)]) scancel) : List[ ?[ok_(boolו), cancel_(int×…)] ] : ?[ok_(boolו); cancel_(int× …)] (← wanted)
  130. 130. A Solution from Concurrent ML (Reppy, 1993) 130 … has a set of (event) primitives we need! choose : List[?T] -> ?T makes a (multiplexed) channel (external choice) wrap : (α -> β) -> ?α -> ?β makes a wrapped channel sok : ?bool, scancel : ?int wrap (λx.[ok=(x,•)]) sok : ?[ok_(boolו)] wrap (λx.[cancel=(x,…)]) scancel : ?[cancel_(int×…)] List(wrap (λx.[ok=(x,•)]) sok; wrap (λx.[cancel=(x,…)]) scancel) : List[ ?[ok_(boolו), cancel_(int×…)] ] choose (List(wrap (λx.[ok=(x,•)]) sok; wrap (λx.[cancel=(x,…)]) scancel)) : ?[ok_(boolו); cancel_(int× …)] (← wanted)
  131. 131. A Solution from Concurrent ML (Reppy, 1993) 131 … has a set of (event) primitives we need! choose : List[?T] -> ?T makes a (multiplexed) channel (external choice) wrap : (α -> β) -> ?α -> ?β makes a wrapped channel sok : ?bool, scancel : ?int wrap (λx.[ok=(x,•)]) sok : ?[ok_(boolו)] wrap (λx.[cancel=(x,…)]) scancel : ?[cancel_(int×…)] List(wrap (λx.[ok=(x,•)]) sok; wrap (λx.[cancel=(x,…)]) scancel) : List[ ?[ok_(boolו), cancel_(int×…)] ] choose (List(wrap (λx.[ok=(x,•)]) sok; wrap (λx.[cancel=(x,…)]) scancel)) cancel(_, )ok(_, ) scancel1 sok (scancel2, ) cancel choose : ?[ok_(boolו); cancel_(int× …)] (← wanted)
  132. 132. Putting them altogether 132 (scancel, )(sok, ) ok cancel cancel(_, )ok(_, ) scancel1 sok (scancel2, ) cancel choose B⊕{ok(bool).•; cancel(int).B&cancel(int).•} A&{ok(bool).•; cancel(int).A⊕cancel(int).•} choice_at A {(A → B) ok finish, (A → B) cancel((B → A) cancel finish)} cancel(_, ) scancel2
  133. 133. Putting them altogether 133 (scancel, )(sok, ) ok cancel cancel(_, )ok(_, ) scancel1 sok (scancel2, ) cancel choose B⊕{ok(bool).•; cancel(int).B&cancel(int).•} A&{ok(bool).•; cancel(int).A⊕cancel(int).•} choice_at A {(A → B) ok finish, (A → B) cancel((B → A) cancel finish)} cancel(_, ) scancel2

×