Asynchronous Message Passing

Similar documents
Asynchronous Computations

Building reactive services using functional programming. Rachel rachelree.se Jet tech.jet.

Programming Safe Agents in Blueprint. Alex Muscar University of Craiova

MBrace. MBrace MBrace. MBrace.Azure

Lwt: a Cooperative Thread Library

The F# Team Microsoft

Imperative programming in F#

Reactive programming, WinForms,.NET. Björn Dagerman

CS 6112 (Fall 2011) Foundations of Concurrency

MultiThreading 07/01/2013. Session objectives. Introduction. Introduction. Advanced Java Programming Course

Advanced Java Programming Course. MultiThreading. By Võ Văn Hải Faculty of Information Technologies Industrial University of Ho Chi Minh City

Processor speed. Concurrency Structure and Interpretation of Computer Programs. Multiple processors. Processor speed. Mike Phillips <mpp>

Programovací jazyky F# a OCaml. Chapter 6. Sequence expressions and computation expressions (aka monads)

Continuations and Continuation-Passing Style

Problems with Concurrency. February 19, 2014

Message-passing concurrency in Erlang

Deadlock. Lecture 4: Synchronization & Communication - Part 2. Necessary conditions. Deadlock handling. Hierarchical resource allocation

Operating Systems. Lecture 4 - Concurrency and Synchronization. Master of Computer Science PUF - Hồ Chí Minh 2016/2017

Ch 9: Control flow. Sequencers. Jumps. Jumps

Actors in the Small. Making Actors more Useful. Bill La

27/04/2012. We re going to build Multithreading Application. Objectives. MultiThreading. Multithreading Applications. What are Threads?

OCaml Data CMSC 330: Organization of Programming Languages. User Defined Types. Variation: Shapes in Java

Index. Cambridge University Press Functional Programming Using F# Michael R. Hansen and Hans Rischel. Index.

Processes. Process Concept

re-exam Concurrent Programming tda383/dit390 Date: Time: 14:00 18:00 Place: Maskinhuset (M)

MultiThreading. Object Orientated Programming in Java. Benjamin Kenwright

CS Programming Languages: Scala

JS Event Loop, Promises, Async Await etc. Slava Kim

Real Time Operating System: Inter-Process Communication (IPC)

Side Trip into Java: Enumeration Types. CS61B Lecture #36. Making Enumerals Available Elsewhere. Enum Types in Java. import static checkers.piece.

CS61B Lecture #36. DSIJ, Chapter 10, HFJ, pp Today: A Brief Side Trip: Enumeration types.

Parallel Code Smells: A Top 10 List

Stuart

Clojure. A (not-so-pure) functional approach to concurrency. Paolo Baldan Linguaggi per il Global Computing AA 2016/2017

Computer Science 21b (Spring Term, 2015) Structure and Interpretation of Computer Programs. Lexical addressing

MCSA Universal Windows Platform. A Success Guide to Prepare- Programming in C# edusum.com

AST: scalable synchronization Supervisors guide 2002

Chapter 3: Processes. Operating System Concepts 8 th Edition,

Only one thread can own a specific monitor

Futures. Prof. Clarkson Fall Today s music: It's Gonna be Me by *NSYNC

CMSC 330: Organization of Programming Languages

Dynamic Types, Concurrency, Type and effect system Section and Practice Problems Apr 24 27, 2018

Topic 5: Examples and higher-order functions

MASSACHUSETTS INSTITUTE OF TECHNOLOGY Computer Systems Engineering: Spring Quiz I Solutions

Threads and Parallelism in Java

Introduction to Typed Racket. The plan: Racket Crash Course Typed Racket and PL Racket Differences with the text Some PL Racket Examples

Reminder from last time

Extensions to Barrelfish Asynchronous C

Chapter 3: Processes. Operating System Concepts 8th Edition

Distributed Object-Based Systems The WWW Architecture Web Services Handout 11 Part(a) EECS 591 Farnam Jahanian University of Michigan.

COS 326 David Walker Princeton University

INF 212 ANALYSIS OF PROG. LANGS FUNCTION COMPOSITION. Instructors: Crista Lopes Copyright Instructors.

Problems with Concurrency

Common Design Principles for kdb+ Gateways

C++11 threads -- a simpler interface than pthreads Examples largely taken from 013/02/24/investigating-c11-threads/

CMSC 330: Organization of Programming Languages. Threads Classic Concurrency Problems

Midterm Exam Solutions and Grading Guidelines March 3, 1999 CS162 Operating Systems

The Dining Philosophers Problem CMSC 330: Organization of Programming Languages

Multiple Inheritance. Computer object can be viewed as

Final Exam Solutions May 11, 2012 CS162 Operating Systems

Today: Synchronization. Recap: Synchronization

CSE 230. Concurrency: STM. Slides due to: Kathleen Fisher, Simon Peyton Jones, Satnam Singh, Don Stewart

CSCI-1200 Data Structures Fall 2009 Lecture 25 Concurrency & Asynchronous Computing

C++ : Object Oriented Features. What makes C++ Object Oriented

CSE 451: Operating Systems Winter Lecture 7 Synchronization. Steve Gribble. Synchronization. Threads cooperate in multithreaded programs

Last Class: Clock Synchronization. Today: More Canonical Problems

Process Concept. Minsoo Ryu. Real-Time Computing and Communications Lab. Hanyang University.

CMSC 330: Organization of Programming Languages. The Dining Philosophers Problem

Synchronization II: EventBarrier, Monitor, and a Semaphore. COMPSCI210 Recitation 4th Mar 2013 Vamsi Thummala

Overview. CMSC 330: Organization of Programming Languages. Concurrency. Multiprocessors. Processes vs. Threads. Computation Abstractions

Lecture 24: Java Threads,Java synchronized statement

CSE 486/586 Distributed Systems

Week 7. Concurrent Programming: Thread Synchronization. CS 180 Sunil Prabhakar Department of Computer Science Purdue University

COMPSCI 230 Threading Week8. Figure 1 Thread status diagram [

Written Presentation: JoCaml, a Language for Concurrent Distributed and Mobile Programming

CS 556 Distributed Systems

Programming Idioms for Transactional Events

User-defined Functions. Conditional Expressions in Scheme

A Third Look At ML. Chapter Nine Modern Programming Languages, 2nd ed. 1

Inside core.async Channels. Rich Hickey

Actor-Based Concurrency: Implementation and Comparative Analysis With Shared Data and Locks Alex Halter Randy Shepherd

Producer Consumer in Ada

ELEC 377 Operating Systems. Week 1 Class 2

CS 162 Operating Systems and Systems Programming Professor: Anthony D. Joseph Spring 2004

multiprocessing HPC Python R. Todd Evans January 23, 2015

Software Design and Analysis for Engineers

Last Class: Synchronization

Page 1. Analogy: Problems: Operating Systems Lecture 7. Operating Systems Lecture 7

Unified Modeling Language

CS18000: Programming I

SNU Programming Language Theory

! How is a thread different from a process? ! Why are threads useful? ! How can POSIX threads be useful?

Goldibear and the 3 Locks. Programming With Locks Is Tricky. More Lock Madness. And To Make It Worse. Transactional Memory: The Big Idea

List Functions, and Higher-Order Functions

Kapil Sehgal PGT Computer. Science Ankleshwar Gujarat

!! How is a thread different from a process? !! Why are threads useful? !! How can POSIX threads be useful?

CSCD 330 Network Programming

6.821 Jeopardy: The Home Version The game that turns into 6.82fun!

CSCI 2041: Functions, Mutation, and Arrays

Chapter 3: Processes. Operating System Concepts 8th Edition, modified by Stewart Weiss

Transcription:

CITS 3242 Programming Paradigms Part III: Concurrent Programming Topic 15: Asynchronous Message Passing Message passing is an important alternative to shared memory concurrency. It avoids the issues related to interference and locking by making each object the responsibility of only a single thread/task. Communication then occurs by explicitly sending messages, generally asynchronously via queues so that threads are never blocked. 1

Constructs for computation expressions (including asynchronous blocks) Construct let! pat = expr let pat = expr do! expr do expr return expr return! expr use! pat = expr use pat = expr Description Execute the async computation expr and bind its result to pat when it completes. If expr has type Async<'a>, then pat has type 'a. Equivalent to async.bind(expr,(fun pat ->...)). Execute an expression synchronously and bind its result to pat immediately. If expr has type 'a, then pat has type 'a. Equivalent to an ordinary let that binds variables with scope until the end of the block. Equivalent to let! () = expr. Equivalent to let () = expr. Evaluate the expression, and return its value as the result of the containing asynchronous workflow. Equivalent to async.return(expr). Execute the expression as an asynchronous computation, and return its result as the overall result of the containing asynchronous workflow. Equivalent to expr. Like let! but calls Dispose on each variable in the pattern when the enclosing async ends. Equivalent to async.bind(expr,(fun x -> async.using(x,fun pat ->...))) Like let but calls Dispose on each variable in the pattern when the async ends. Equivalent to async.using(expr,(fun pat ->...)). 2

Async static members (there are many more) Member Async.Parallel: seq<async<'a>> -> Async<'a[]> Description Runs the async s in parallel and collects the results. Cancels all when exceptions. Async.RunSynchronously: Async<'a> -> 'a Runs via the thread pool and waits for the result. Async.Start: Async<unit> -> unit Async.SpawnChild: Async<unit> -> Async<unit> StartWithContinuations : Async<'T> * ('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) *?CancellationToken -> unit Queues without waiting. As above, but inherits the cancellation handle from the current async. As above, but then its result is available, executes the first callback, or one of the other two callbacks for exceptions or cancellations. Async.Catch: Async<'a> -> Async<Choice<'a, exn>> Catches errors from an asynchronous computation and returns a Choice result indicating success or failure. Catch makes use of: type Choice<'a,'b> = Choice2_1 of 'a Choice2_2 of b [This slide based on: http://msdn.microsoft.com/en-us/library/dd233250.aspx and http://msdn.microsoft.com/en-us/library/ee370232.aspx which have more details.] 3

Message passing Shared memory is often a natural way to program, but it has some issues. Avoiding deadlocks can be difficult, particularly when putting together components that each use their own locks. As a result, shared memory does not scale well to large programs. Also, shared memory has performance costs: The time to do the lock and unlock operations. Many cores accessing the same address invalidates CPU caching - sharing memory leads to slower access times. When multiple computers are involved, shared memory is generally not an appropriate model. Message passing addresses these issues by making communication explicit. Asynchronous messages are generally preferred so that senders do not have to wait for receivers. Generally messages are queued in a mailbox this means that receivers also do not have to wait unless the mailbox is empty. 4

Asynchronous messages small example open Microsoft.FSharp.Control.Mailboxes let counter = MailboxProcessor.Create(fun inbox -> // returns an async let rec loop(n) = async { do printfn "n = %d, waiting..." n let! msg = inbox.receive() return! loop(n+msg) } loop(0)) val counter : MailboxProcessor<int> > counter.start();; n = 0, waiting... > counter.post(1);; n = 1, waiting... > counter.post(2);; n = 3, waiting... > counter.post(1);; n = 4, waiting... 5

Defining message processors/agents Message-processing components (also called agents) typically use sets of recursive functions, each defining an async. Each function corresponds to a state that determines how the agent will react to the next message. For example, an agent may have a special function/state for when it is waiting for a reply to a message it has sent. If an agent always operates the same way, one state is enough. Arguments can be passed between these functions to represent further information about the current state. // This is the general pattern for an agent let agent = MailboxProcessor.Start(fun inbox -> // The states of the state machine let rec state1(args) = async {... } // Each state s async and state2(args) = async {... } // ends with a call to... // the next state. and staten(args) = async {... } // Enter the initial state state1(initialargs)) 6

Mailbox members Post: 'msg -> unit Posts a message to a mailbox queue. Receive:?timeout:int -> Async<'msg> Returns the next message, waiting asynchronously. If a timeout occurs, then raises a TimeoutException. Scan: ('msg -> Async<'a> option) *?timeout:int -> Async<'a> Scans the mailbox for a message accepted by the function. Returns the chosen result. TryReceive :?timeout:int -> Async<'msg option> If a timeout occurs returns None. (Also TryScan, similarly.) PostAndReply: (AsyncReplyChannel<'reply> -> 'msg) -> 'reply Post a message and await a reply on the channel. The function must build a message containing the reply channel, and the (unique) reply on that channel will be returned. 7

Example: Labs from the project To compare with shared memory and locks, here s how the labs from the project would look as message passing agents with 2 states idle and busy type Agent<'T> = MailboxProcessor<'T> type Cont<'a> = 'a -> unit type delay = int type LabMsg = Rules of Cont<labRules> // Alas, using Agent<labRules> is awkward. DoExp of delay * exp * clientid * Cont<bool> // Ditto ExpDone let postlater (box: Agent<'a>) delay (msg:'a) = Async.Start (async { do! Async.Sleep delay; box.post msg }) type lab = Agent<LabMsg> let lab (labid, rules) = MailboxProcessor.Start(fun inbox -> let rec idle() = async { let! msg = inbox.receive() match msg with Rules rulescont -> rulescont rules; return! idle() DoExp (delay, exp, clid, cont) -> postlater inbox delay ExpDone; return! busy clid cont ExpDone -> failwith "ExpDone received without an experiment in progress" } and busy usingclid cont = async { let! msg = inbox.receive() match msg with Rules rulescont -> rulescont rules; return! busy usingclid cont DoExp (delay, exp, clid, expcont) -> let str = sprintf "BANG! lab%d explodes - host%d is already using it" labid usingclid prstamp -1 str "" ; return! busy usingclid cont ExpDone -> if random 2 = 1 then cont true else cont false; return! idle() } idle() ) 8

Example: Bank accounts To compare with the concurrent code we saw earlier (in Lab 6), we now consider code for bank accounts using messages. This example makes for quite a good comparison between message passing and shared memory with monitors/locks. However, the message passing version doesn t provide exactly the same guarantees we ll consider this after seeing the code. We have a union type with the different kinds of messages. We have an agent that does the message processing. We wrap the agent in a class here, to show how message passing can be combined with standard objects. In particular, this demonstrates how to interface with ordinary synchronous code, 9

Example: Bank accounts with messages type acctmsg = BalanceMsg of AsyncReplyChannel<int> WithdrawMsg of int DepositMsg of int TransferMsg of account * int and account(name:string) = let agent = MailboxProcessor.Start(fun inbox -> let balance = ref 1000 let withdraw amt = balance :=!balance - amt let rec loop() = async { loop() ) let! msg = inbox.receive() match msg with BalanceMsg replych-> replych.reply(!balance) WithdrawMsg amt -> withdraw amt DepositMsg amt -> balance :=!balance + amt TransferMsg (toacct, amt) -> withdraw amt toacct.deposit amt return! loop() } member this.balance = agent.postandreply (fun replychan -> BalanceMsg replychan) member this.name = name member this.withdraw amount = agent.post (WithdrawMsg amount) member this.deposit amount = agent.post (DepositMsg amount) member this.transfer (toacc:account) amount = agent.post (TransferMsg (toacc, amount)) 10

Example: Bank accounts main program let dotransfers (acc:account) toacc () = for i in 1..100 do acc.transfer toacc 100 printfn "%s balance: %d Other balance: %d" acc.name acc.balance toacc.balance // The handout included a sleep here, but in fact it isn t needed printfn "%s balance: %d Other balance: %d" acc.name acc.balance toacc.balance let main() = let acc1=account("account1") let acc2=account("account2") startthread (dotransfers acc1 acc2) startthread (dotransfers acc2 acc1) main() // The output is as follows Account2 balance: -9000 Other balance: 1000 Account1 balance: -9000 Other balance: 1000 Account2 balance: 1000 Other balance: 1000 Account1 balance: 1000 Other balance: 1000 11

Notes on bank account example The balance and name methods are synchronous (they wait for the result) while the others are asynchronous. For the balance, this requires a reply channel The channel is sent in the message, and then PostAndReply waits. Inside the agent, we have strong guarantees about non-interference. Only one thread can be running within the agent at a time. For a transfer, our guarantees are not quite the same as the version in Lab 6 which locks both accounts. The total money in the accounts appears to change. This is common in message passing: consistency properties involving multiple agents need to be reconsidered. In this case, we need to include the money in messages waiting to be delivered if we do, this will never change. It is tricky to calculate properties involving many agents, like the total sum of money, however there are algorithms to do this by sending special marker messages to form a global snapshot which is consistent with the actual state. This reflects the asynchronous nature of messages. 12