programming paradigms for concurrency n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Programming Paradigms for Concurrency PowerPoint Presentation
Download Presentation
Programming Paradigms for Concurrency

Loading in 2 Seconds...

play fullscreen
1 / 57

Programming Paradigms for Concurrency - PowerPoint PPT Presentation


  • 244 Views
  • Uploaded on

Programming Paradigms for Concurrency. Lecture 10 Part III – Message Passing Concurrency. Message Passing Paradigms. Two important categories of MP paradigms: Actor or agent-based paradigms unique receivers : messages are sent directly from one thread to another Channel-based paradigms

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Programming Paradigms for Concurrency' - gavan


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
programming paradigms for concurrency

Programming Paradigms for Concurrency

Lecture 10

Part III – Message Passing Concurrency

message passing paradigms
Message Passing Paradigms

Two important categories of MP paradigms:

  • Actor or agent-based paradigms
    • unique receivers: messages are sent directly from one thread to another
  • Channel-based paradigms
    • multiple receivers: messages are sent to channels that are shared between threads
channel based message passing
Channel-based Message Passing
  • threads perform local computations and synchronize via MP over channels
  • channels can be shared between threads(no unique receiver)
  • communication is typically synchronous (blocking send)
  • threads are anonymous
  • threads and channels are created dynamically

B

A

A

a brief history of channel based paradigms
A Brief History of Channel-Based Paradigms
  • Hoare 1978, 1985: Communicating sequential processes (CSP)
  • Milner 1980: Calculus of communicating systems (CCS)
  • May et al. 1985: Occam language
  • Reppy 1991: Concurrent ML
  • Milner, Parrow, Walker 1992: ¼ calculus
  • Gropp, Lusk, Skjellum 1994: Message passing interface (MPI)
  • Griesemer, Pike, Thompson 2009: Go language
concurrent ml
Concurrent ML
  • higher-order concurrent language
  • extension of Standard ML
  • part of the SML of New Jersey language distribution: http://www.smlnj.org/
  • first-class events: provides special event type and event combinators enables building protocol abstractions
  • threads and channels are garbage collected supports speculative communication
simple example reference cells1
Simple Example: Reference Cells

signatureCELL =

sig

type 'a cell

val cell : 'a -> 'a cell

val read : 'a cell -> 'a

val write : 'a cell -> 'a -> unit

end

cell x : creates new cell

holding value x

read c : retrieves value

stored in cell c

write c x: updates cell c

to hold value x

cell implementation
Cell implementation
  • each cell has an associated thread holding the stored value
  • each cell encapsulates two channels to its associated thread for updating/retrieving the stored value
cell implementation1
Cell Implementation

reqCh?READ

datatype 'a request = READ | WRITE of 'a

datatype 'a cell = CELL of {

reqCh : 'a request chan,

replyCh : 'a chan

}

C1(x)

C2(x)

reqCh?WRITE(y)

replyCh!x

implementing read and write
Implementing read and write

reqCh?READ

fun read (CELL {reqCh, replyCh}) =

(send (reqCh, READ); recvreplyCh)

fun write (CELL {reqCh, ...}) x =

send(reqCh, WRITE x)

C1(x)

C2(x)

reqCh?WRITE(y)

replyCh!x

send : ('a chan* 'a) -> unit

send (ch, x) : send value x over channel ch

recv : 'a chan -> 'a

recvch : receives a value from channel ch

implementing cell
Implementing cell

reqCh?READ

fun cell x =

let valreqCh = channel ()

valreplyCh = channel ()

fun loop x =

caserecvreqChof

READ => (send (replyCh, x); loop x)

| WRITE y => loop y

in

spawn (fn () => loop x);

CELL{reqCh = reqCh, replyCh = replyCh}

end

C1(x)

C2(x)

reqCh?WRITE(y)

channel : unit -> 'a chan

channel () : creates a new channel

replyCh!x

spawn : (unit -> unit) -> unit

spawn f : creates a new thread executing f

selective communication
Selective Communication

Allow a process to block on a nondeterministic choice of several blocking communications

  • the first communication that becomes enabled is chosen
  • if two or more communications are available simultaneously, then one is chosen nondeterministically.
simplified cell implementation
Simplified Cell Implementation

datatype 'a cell = CELL of {

readCh : 'a chan,

writeCh : 'a chan

}

fun read (CELL{readCh, ...}) = recvreadCh

fun write (CELL{writeCh, ...}) = send (writeCh, x)

C(x)

readCh?y

writeCh!x

simplified cell implementation1
Simplified Cell Implementation

C(x)

readCh?y

writeCh!x

fun cell x =

let valreadCh = channel ()

valwriteCh = channel ()

fun loop x = select [

wrap (sendEvt(readCh, x), fn () => loop x),

wrap (recvEvtwriteCh, loop)

]

in

spawn (fn () => loop x);

CELL{readCh = readCh, writeCh = writeCh}

end

first class events
First-Class Events

Design principle for MP programming

  • use communication primitives to implement complex protocols
  • use abstraction to hide actual communication channels and thus details of thread interactions
  • implement abstract protocols

Problem: standard abstraction mechanisms provided by sequential languages hide too much.

example rpc server
Example: RPC Server
  • Server provides service via a remote procedure call (RPC) protocol
  • RPC protocol:
    • a client must send a request before trying to read a reply
    • following a request, a client must read exactly one reply before issuing another request
example rpc server1
Example: RPC Server

fundoit request = ... (* the actual service *)

  • fun serverLoop () =
  • ifserviceAvailable () then
  • let valrequest = recvreqChin
  • send (replyCh, doit request);
  • serverLoop ()
  • end
  • else doSomethingElse ()
  • Problem: if some client does not respect the RPC protocol, then the server may get out of sync.
example rpc server2
Example: RPC Server

fun serverLoop() =

ifserviceAvailable ()then

let valrequest = recvreqChin

send (replyCh, doit request);

serverLoop ()

end

else doSomethingElse ()

Solution: use procedural abstraction to hide protocol details on client side

funclientCall x = (send (reqCh, x); recvreplyCh)

  • Problem: client blocks if service is not available
  • one would like to use selective communication in client, but procedural abstraction hides too much
first class synchronous events1
First-Class Synchronous Events
  • Concurrent ML provides special event typetype ‘a event
  • Events decouple the description of synchronous operations from the actual act of synchronizing on the operation

valsync : ‘a event -> ‘a

  • Event combinatorsenable construction of complex events that implement abstract protocols
primitive events
Primitive Events

valrecvEvt : ‘a chan -> ‘a event

valsendEvt : ‘a chan * ‘a -> unit event

recv and send are defined using these primitive events:

funrecvch = sync (recvEvtch)

funsend(ch, x) = sync (sendEvt(ch, x))

post synchronization actions wrap
Post-Synchronization Actions: wrap

valwrap : ‘a event * (‘a -> ‘b) -> ‘b event

wrap (e, f) : returns an event that when synchronized,

synchronizes e and applies f to the result

selective synchronization choose
Selective Synchronization: choose

valchoose : ‘a event list-> ‘a event

choosees : returns an event that when synchronized, nondeterministically synchronizes one enabled event in es.

funselectes = sync(choosees)

simplified cell implementation revisited
Simplified Cell Implementation (revisited)

C(x)

readCh?y

writeCh!x

fun cell x =

let valreadCh = channel ()

valwriteCh = channel ()

fun loop x = select [

wrap (sendEvt(readCh, x), fn () => loop x),

wrap (recvEvtwriteCh, loop)

]

in

spawn (fn () => loop x);

CELL{readCh = readCh, writeCh = writeCh}

end

example rpc client revisited
Example: RPC Client (revisited)

funclientCall x : ‘a -> ‘b option event =

wrap (sendEvt (reqCh, x), fn () => SOME (recvreplyCh))

fun timeOut () : ‘b option event =

let valto = Time.now + Time.fromSeconds 60 in

  • wrap (atTimeEvt to, fn () => NONE)

end

fun client request : ‘a -> ‘b option =

select [clientCall request, timeOut ()]

example swap channels
Example: Swap Channels

Swap channels enable symmetric communication between threads where values are exchanged in both directions.

signatureSWAP_CHANNEL =

sig

type ‘a swap_chan

valswapChannel : unit -> ‘a swap_chan

val swap : (‘a swap_chan * ‘a) -> ‘a event

end

swap channel implementation 1 st try
Swap Channel Implementation (1st try)

datatype ‘a swap_chan = SC of ‘a chan

funswapChannel () = SC (channel ())

fun swap (SC ch, msgOut) =

choose [

wrap (recvEvtch,

fnmsgIn => (send(ch, msgOut); msgIn)),

wrap (sendEvt (ch, msgOut),

fn () => recvinCh)

]

swap mismatch
Swap mismatch

P1

P2

Q1

Q2

swap(ch, 1)

swap(ch, 2)

swap(ch, 3)

swap(ch, 4)

send(ch, 1)

recvch

send(ch, 3)

recvch

recvch

send(ch, 2)

recvch

send(ch, 4)

Race on shared channel!

pre synchronization actions guard
Pre-Synchronization Actions: guard

valguard : (unit -> ‘a event) -> ‘a event

guard f: returns an event that when synchronized, first evaluates f and then synchronizes the resulting event

swap channel implementation
Swap Channel Implementation

datatype ‘a swap_chan = SC of (‘a * ‘a chan) chan

funswapChannel () = SC (channel ())

fun swap (SC ch, msgOut) =

guard (fn () =>

let valinCh = channel () in

choose [

wrap (recvEvtch,

fn (msgIn, outCh) => (send (outCh, msgOut); msgIn)),

wrap (sendEvt (ch, (msgOut, inCh)),

fn () => recvinCh)

]

end)

fresh private channel for each swap event

example rpc server revisited
Example: RPC Server (revisited)

fun serverLoop() =

let valrequest = recvreqChin

send (replyCh, doit request);

serverLoop ()

end

  • funclientCall x =
  • guard (fn () => send (reqCh, x); recvEvtreplyCh)
  • fun client request =
  • select [clientCall request, timeoutEvent ()]
client timeout
Client Timeout

T

C1

S

C2

recvreqCh

send(reqCh,1)

atTimeEvt

doit 42

send(replyCh,42)

send(reqCh,2)

deadlock

Server S and other clients might deadlock if client C1 times out

cancellation withnack
Cancellation: withNack

valwithNack : (unit event -> ‘a event) -> ‘a event

  • When withNackf is used in a select, the select evaluates fwith a fresh abort event nack.
  • The resulting event fnack is then used with the other events in the select.
  • If the select does not choose fnack when it is synchronized, then nack is synchronized, effectively informing fnack that it is not chosen.
example rpc server revisited1
Example: RPC Server (revisited)

fun serverLoop() =

let val(request, nack) = recvreqChin

select [sendEvt (replyCh, doit request),nack];

serverLoop ()

end

  • funclientCall x = withNack (fn nack =>
  • send (reqCh, (x, nack)); recvEvtreplyCh)
  • fun client request =
  • select [clientCall request, timeoutEvent ()]
client timeout1
Client Timeout

T

C1

S

C2

recvreqCh

send(reqCh,(1,na))

atTimeEvt

doit 42

na

na

send(reqCh,(2,na))

recvreqCh

more features of concurrent ml
More Features of Concurrent ML
  • more event combinators
  • buffered channels
  • multicast channels
  • sync variables
  • built-in RPC support
  • ...
event represenation
Event Represenation

Canonicalform of an event is a binary tree with:

  • wrapped base-event values as leaves
  • choice operators as internal nodes

Canonical form is obtained using the following equivalences:

wrap(wrap(ev,g),f) = wrap(ev, f ± g)

wrap(choose(ev1,ev2),f) =

choose(wrap(ev1,f), wrap(ev2,f))

event represenation1
Event Represenation

choose

choose

choose

wrap

wrap

wrap

recv

choose

recv

wrap

wrap

wrap

wrap

wrap

wrap

send

recv

send

recv

base event representation
Base Event Representation

Each base event is a record of three functions:

pollFn

doFn

blockFn

test if base event is enabled

synchronize on the enabled base event

block calling thread on the base event

protocol for sync
Protocol for sync

Each call to sync from a PCL thread executes the following protocol:

  • Polling Phase: poll the base events using pollFn to see if any of them are enabled
  • Commit Phase: if one or more base events are enabled, pick one and synchronize on it using doFn
  • Blocking Phase: if no base events are enabled:
    • enqueue a continuation for the calling thread on each of the base events using its blockFn
    • switch to some other thread
    • eventually, some other thread will complete the synchronization.
first class continuations
First-Class Continuations

type ‘a cont

valcallcc : (‘a cont -> ‘a) -> ‘a

val throw : ‘a cont -> ‘a -> ‘b

event representation
Event Representation

datatypeevent_status =

INIT | WAITING | SYNCHED

typeevent_state = event_status ref

datatype ‘a evt =

BEVT of {

pollFn : unit -> bool

doFn : ‘a cont -> unit

blockFn : (event_state * ‘a cont) -> unit

}

| CHOOSE of ‘a evt * ‘a evt

implementing sync
Implementing sync

funsyncev = callcc (fnresumeK =>

let fun poll (ev, enabled) = ...

fundoEvt enabled = ...

andblockThd () = ...

in

doEvt (poll (ev, []))

end)

implementing sync1
Implementing sync

funsyncev = callcc (fnresumeK =>

let fun poll (BEVT{pollFn, doFn, ...}, enabled) =

ifpollFn () thendoFn::enabled

else enabled

| poll (CHOOSE(ev1, ev2)), enabled) =

poll(ev2, poll(ev1, enabled))

fundoEvt enabled = ...

andblockThd () = ...

in

doEvt (poll (ev, []))

end)

implementing sync2
Implementing sync

funsyncev = callcc (fnresumeK =>

let fun poll (ev, enabled) = ...

fundoEvt [] = blockThd ()

| doEvt (doFn::enabled) =

doFnresumeK;

(* if doFn terminates then sync

attempt failed, so continue *)

doEvt enabled

andblockThd () = ...

in

doEvt (poll (ev, []))

end)

implementing sync3
Implementing sync

funsyncev = callcc (fnresumeK =>

let fun poll (ev, enabled) = ...

fundoEvt enabled = ...

andblockThd () =

let valflg = ref INIT

fun block (BEVT {blockFn, ...}) =

blockFn (flg, resumeK)

block (CHOOSE (ev1, ev2)) =

(block ev1; block ev2)

in

block ev; flg := WAITING; dispatch()

end

in

doEvt (poll (ev, []))

end)

implementing wrap
Implementing wrap

funwrap (BEVT {pollFn, doFn, blockFn}, f) =

BEVT {

pollFn = pollFn,

doFn = fn k => callcc (fnretK =>

throw k (f (callcc (fn k’ =>

doFn k’;

throw retK ()))))),

blockFn = fn (flg, k) => callcc (fnretK =>

throw k (f (callcc (fn k’ =>

blockFn(flg, k’);

throw retK ())))))

| wrap (CHOOSE(ev1, ev2), f) =

CHOOSE(wrap(ev1, f), wrap(ev2, f))

event representation1
Event Representation

datatype ‘a chan = CH of {

lock : bool ref,

sendq : (‘a * unit cont) queue

recvq : (event_state * ‘a cont) queue

}

implementing recvevt
Implementing recvEvt

funrecvEvt (CH {lock, sendq, recvq}) =

let fun pollFn () = ...

fundoFn k = ...

funblockFn (flg : event_state, k) = ...

in

BEVT {pollFn = pollFn, doFn = doFn,

blockFn = blockFn}

end

implementing recvevt1
Implementing recvEvt

funrecvEvt (CH {lock, sendq, recvq}) =

let fun pollFn () = not(isEmptyQ(sendq))

fundoFn k = ...

funblockFn (flg : event_state, k) = ...

in

BEVT {pollFn = pollFn, doFn = doFn,

blockFn = blockFn}

end

implementing recvevt2
Implementing recvEvt

funrecvEvt (CH {lock, sendq, recvq}) =

let fun pollFn () = ...

fundoFn k =

let val_ = spinLock lock

val item = dequeuesendq

in

spinUnlock lock;

case item of

NONE => ()

| SOME(msg, sendK) =>

(enqueueRdysendK; throw k msg)

end

funblockFn (flg : event_state, k) = ...

in BEVT {...} end

implementing recvevt3
Implementing recvEvt

funrecvEvt (CH {lock, sendq, recvq}) =

let fun pollFn () = ...

fundoFn k = ...

funblockFn (flg : event_state, k) =

spinLock lock;

casedequeuesendqof

SOME (msg, sendK) =>

( spinUnlock lock;

flg := SYNCHED;

enqueueRdysendK;

throw k msg )

| NONE =>

( enqueue (recvq, (flg, k));

spinUnlock lock ) end

in BEVT {...} end

further reading
Further Reading

For more details about CML see

  • CML: A higher-order concurrent language.J. Reppy. In PLDI 1991.
  • Concurrent Programming in ML. J. Reppy, Cambridge University Press, 1999.
  • Toward a parallel implementation of Concurrent ML. J. Reppy and Y. Xiao. In DAMP 2008.
  • Parallel Concurrent ML.J. Reppy, C. Russo, and Y. Xiao. In ICFP 2009.
project proposals
Project Proposals
  • Performance/Conciseness Evaluation of Concurrent Programming Paradigms

Compare idiomatic implementations of the same algorithm in Scala using different programming paradigms:

    • a sequential implementation
    • a concurrent implementation based on actors
    • a concurrent implementation based on shared memory
project proposals1
Project Proposals
  • First-Class Synchronous Events in Scala
    • Take inspiration from the Scala Actor Library and the CML library
    • Implement a Scala library supporting first-class synchronous events.
project proposals2
Project Proposals
  • Verification of Scala Actor Programs
    • Implement a non-trivial Scala Actor program or take an existing one
    • Manually compute finite-state abstractions of all actors
    • Verify properties of the abstracted program using a formal verification tool for MP programs

Please choose your project until 12/22/2010!