Com S 541 Lecture -*- Outline -*- * Message-Passing Concurrency (Ch 5) Based on Peter van Roy and Seif Haridi's book, "Concepts, Techniques, and Models of Computer Programming" (MIT Press, 2004), where all references that are not otherwise attributed are found. ** motivation ------------------------------------------ MESSAGE-PASSING CONCURRENCY (5) def: message passing is a programming style in which a program consists of independent entities that interact by sending messages asynchronously Importance: ------------------------------------------ Q: What is asynchronous? Not waiting for a reply Q: What's the importance of message passing? - multi-agent systems (same as message passing systems) - natural for distributed systems reflects structure of system and its costs - lends itself to building highly releiable systems failures don't make other entities hang ** concepts ------------------------------------------ CONCEPTS new idea: asynchronous communication channel - named - all clients can always send - server can read all messages Fundamentally nondeterministic Port: channel with an associated stream send = append to stream read = read from stream ------------------------------------------ ** operational semantics ------------------------------------------ SYNTAX Syntax: ::= ... | {NewPort X Y} | {Send X Y} {NewPort S P} creates port named P with stream S {Send P X} appends X to stream corresponding to P ------------------------------------------ Q: Why can't we write this in the declarative model? no, that would violate determinism of the declarative model Note: could try using streams to be ports... fun {NewPort S} fun {Send X} S1 in S = X|S1 S1 end end But then the result of {NewPort S} can't be used by 2 clients. ------------------------------------------ MUTABLE STORE m in MutableStore = Variable -> Variable Operations: {}: MutableStore update: MutableStore -> Variable x Variable -> MutableStore lookup: MutableStore x Variable -> Variable lookup(update(m)(y,x), z) = if z == y then x else lookup(m,z) Notation: write x:y for a binding in MutableStore typical m is {p1:s1, p2:s2} update({p1:s1})(p2, s2) = {p1:s1, p2:s2} lookup({p1:s1, p2:s2}, p1) = s1 ------------------------------------------ ------------------------------------------ SEMANTICS Sequential (-d->) configurations: (ST,s,m) in State = Stack x Store x MutableStore + Message Message = String Stack = ( x Environment)* Store = Variable -> Value T = Message + { (nil,s,m) | s in Store, m in MutableStore} [NewPort call] (({NewPort X Y},E)|Rest, s, m) -d-> (Rest, s', m') where unbound(s,E(Y)) and n is a port name and n not in range(s) and s' = bind(s)(s(E(Y)),n) and m' = update(m)(E(Y), E(X)) [Send call] (({Send X Y},E)|Rest, s, m) -d-> (Rest, s'', m') where determined(s,E(X)) and s(E(X)) is a port name and lookup(m, E(X)) = z and z' = next(s) and s' = alloc(s) and m' = update(m)(E(X), z') and l = '|'(E(Y) z') and s'' = bind(s')(s'(z), l) ------------------------------------------ recall that Store is more complex if we also want ByNeed triggers Q: What should happen if we do {NewPort S P} and P is already bound? raise an error condition (work that out?) Q: What should happen if we do {Send P Y} and P is not a port? raise an error condition Q: What should happen if we do {Send P Y} and P is unbound? suspend Q: What should happen if we do {Send P Y} and Y is unbound? doesn't matter, this is okay Q: What should happen in [Send call] if m(E(X)) is not defined? That can't happen, port names are always associated with variables. This is simplified, in that the end of the stream is supposed to be a read-only view, not just a variable. Q: Does this affect garbage collection? Yes, - y is reachable if m contains x:y and x is reachable - if x is unreachable, and m contains x:y, then remove x:y from m.