570 likes | 682 Views
Concurrent programming is easy Bertrand Meyer Kirkland, WG 2.3, July 2012. h e is actually getting. You mean. ERC money. for. this?. What this is about. SCOOP: a model for bringing concurrent programming under control Not new (goes back to 90s)
E N D
Concurrent programming is easyBertrand MeyerKirkland, WG 2.3, July 2012
he is actually getting You mean ERC money for this?
What this is about • SCOOP: a model for bringing concurrent programming under control • Not new (goes back to 90s) • But in recent years has been patiently refined (PhD theses) and implemented (now part of standard EiffelStudio) • And is receiving a new impetus
The issue that SCOOP tackles Can we bring concurrent programmingto the same levelof abstraction and convenienceas sequential programming?
Two key goals • Retain the modeling power of object-oriented programming, in its Eiffel variant with contracts • Retain “reasonability”
Dijkstra 68 • ... [O]urintellectual powers are rather geared to master static relations and our powers to visualize processes evolving in time are relatively poorly developed. • For that reason we should do ... our utmost to shorten the conceptual gap between the static program and the dynamic process, to make the correspondence between the program (spread out in text space) and the process (spread out in time) as trivial as possible.
Concurrent programming today Allen Downey: The Little Green Book of Semaphores, greenteapress.com/semaphores/
Reasoning from APIs • transfer (source, target: ACCOUNT; • amount: INTEGER) • -- Transfer amount from source to target. • require • sourcebalance >= amount • do • sourcewithdraw (amount) • targetdeposit (amount) • ensure • sourcebalance = old sourcebalance – amount • targetbalance = old targetbalance + amount • end invariantbalance >= 0
Reasoning from APIs • transfer (source, target: ACCOUNT; • amount: INTEGER) • -- Transfer amount from source to target. • require • sourcebalance >= amount • do • sourcewithdraw (amount) • targetdeposit (amount) • ensure • sourcebalance = old sourcebalance – amount • targetbalance = old targetbalance + amount • end
Reasoning from APIs • if acc1.balance >= 100 then transfer (acc1, acc2, 100) end • if acc1.balance >= 100 then transfer (acc1, acc3, 100) end • transfer (source, target: ACCOUNT; • amount: INTEGER) • -- Transfer amount from source to target. • require • sourcebalance >= amount • do • sourcewithdraw (amount) • targetdeposit (amount) • ensure • sourcebalance = old sourcebalance – amount • targetbalance = old targetbalance + amount • end invariantbalance >= 0
Example 2: hexapodrobot • Hind legs have force sensors on feet and retraction limitswitches
Hexapodlocomotion Ganesh Ramanathan, Benjamin Morandi, IROS 2011 • Alternating protraction and retraction of tripod pairs • Begin protraction only if partner legs are down • Depress legs only if partner legs have retracted • Begin retraction when partner legs are up
Hexapodcoordinationrules • R1: Protractioncanstartonlyifpartnergroup on ground • R2.1: Protractionstarts on completion of retraction • R2.2: Retractionstarts on completion of protraction • R3: Retractioncanstartonlywhenpartnergroupraised • R4: Protractioncan end onlywhenpartnergroupretracted Dürr, Schmitz, Cruse: Behavior-based modeling of hexapod locomotion: linking biology & technical application, in Arthropod Structure & Development, 2004
Hexapodcoordinationrules • R1: Protractioncanstartonlyifpartnergroup on ground • R2.1: Protractionstarts on completion of retraction • R2.2: Retractionstarts on completion of protraction • R3: Retractioncanstartonlywhenpartnergroupraised • R4: Protractioncan end onlywhenpartnergroupretracted Dürr, Schmitz, Cruse: Behavior-based modeling of hexapod locomotion: linking biology & technical application, in Arthropod Structure & Development, 2004
SCOOP version • begin_protraction (partner, me: separate LEG_GROUP) • require • melegs_retracted • partnerlegs_down • not partnerprotraction_pending • do • tripodlift • meset_protraction_pending • end
The design of SCOOP (and this presentation) • To achieve the stated goals, SCOOP makes a number of restrictionson the concurrent programming model • This presentation explains these restrictions • The goal is not to limit programmers but to enable them to reasonabout their programs
Handling concurrency simply • SCOOP narrows down the distinction between sequential & concurrent programming to six properties, studied next: • (A) Single vs multiple “processors” • (B) Regions • (C) Synchronous vs asynchronous calls • (D) Semantics of argument passing • (E)Semantics of resynchronization (lazy wait) • (F) Semantics of preconditions
Actions The starting point (A): processors • To perform a computation is • To apply certainactions • To certainobjects • Using certainprocessors Objects Processor Sequential: one processor Concurrent: any number of processors
Actions What makes an application concurrent? • Processor:Thread of control supporting sequential execution of instructions on one or more objects • Can be implemented as: • Computer CPU • Process • Thread • The SCOOP model is abstract and does not specify the mapping to such actual computational resources Objects Processor
Object-oriented programming • The key operation is “feature call” • x f (args) • where x, the targetof the call, denotes an object to which the call will apply the feature f • Which processor is in charge of executing such a call?
(B): Regions • All calls targeting a given object will be executed by a single processor • The set of objects handled by a given processor is called a region • The processor in charge of an object is its handler
Reasoning about objects: sequential • {INV andPrer}bodyr {INV andPostr} • ___________________________________ • {Prer’ } x.r (a) {Postr’ } Onlynproofsifnexported routines! Priming represents actual-formal argument substitution The concurrent version of this rule will come later!
In a concurrent context • Onlynproofsifnexported routines? • {INV andPrer}bodyr {INV andPostr} • ___________________________________ • {Prer’} x.r (a) {Postr’} Client 3 Client 2 Client 1 r3 r2 r1 No overlapping! Reasonability
SCOOP restriction: one handler per object • One processor per object: “handler” • At most one feature (operation) active on an object at any time Reasonability
Regions • The notion of handler implies a partitioning of the set of objects: • The set of objects handled by a given processor is called a region • Handler rule implies one-to-one correspondence between processors and regions
An aside: processor collection Alexander Kogtenkov,MSEPT 2012 • Processors, like objects, can become unreachable! • Object and processor collection is intertwined • LO = s* (BR r (LP)) • LP = BP h (LO) References Basic roots Live objects Root objects Live processors Basic processors Handler
x.r (a) (C) The sequentialview: O-O featurecalls Client Supplier previous x.r(a) next r (x : A) do … end Processor
(C) The concurrent form of call: asynchronous Client Supplier previous x.r (a) next r (x : A) do … end Supplier’s handler Client’s handler
The two forms of O-O call • To wait or not to wait: • If same processor, synchronous • If different processor, asynchronous • Difference must be captured by syntax: • x: T • x:separateT-- Potentiallydifferent processor • Fundamental semantic rule: a call x.r(a) • Waits (i.e. is synchronous) for non-separate x • Does not wait (is asynchronous) for separate x Reasonability
Why potentially separate? • separatedeclaration does not specify processor: only states that the object might be handled by a different processor • In class A: x: separateB • In class B: y: separateA • In some execution the value of x.y might be a reference to an object in the current region (including Currentitself)
Call vs application • With asynchrony we must distinguish between feature call and feature application • The execution of • xr (...) • is the call, and (with x separate) will not wait (the client just logs the call) • The execution of r happens later and is called the feature application
Consistency rules: avoiding traitors nonsep:T sep:separateT nonsep:= sep nonsep.p(a) Traitor! Traitor avoidance: Piotr Nienaltowski’s type system for SCOOP Reasonability
(D) Access controlpolicy • Since separate calls are asynchronous there is a real danger of confusion • Consider: • my_stack: separateSTACK [T] • … • my_stack.put(a) • … Instructions not affecting stack… • y := my_stack.item Reasonability
(D) Access controlpolicy • SCOOP requires the target of a separate call to be a formal argument of enclosing routine: • my_stack: separateSTACK [T] • … • my_stack.put(a) • … Instructions not affecting stack… • y := my_stack.item ) some_routine( do end Reasonability
(D) Separate argument rule The target of a separate call must be an argument of the enclosing routine Separate call: x.f (...) where x is separate
(D) Wait rule A routine call guarantees exclusive access to the handlers (the processors) of all separate arguments some_routine(nonsep_a, nonsep_b, sep_c, sep_d, sep_e) Exclusive access to sep_c, sep_d, sep_ewithin a_routine Reasonability
Dining philosophers in SCOOP (1) • class PHILOSOPHERfeature • live • do • from getup until over loop • think ;eat (left,right)end • end • eat ( l, r: separateFORK ) • -- Eat, having grabbed land r. • do … end • getup do … end • over: BOOLEAN • end
Dining philosophers in SCOOP (2) • class PHILOSOPHERinherit • REPEATABLE • rename • setupasgetup • redefinestep end • feature {BUTLER} • step • do • think ;eat (left, right) • end • eat (l, r: separateFORK) • -- Eat, having grabbed land r. • do … end • end Reasonability
The general notion of process • SCOOP integrates inheritance and other O-O techniques with concurrency, seamlessly and without conflicts (“inheritance anomaly”) • No need for built-in notion of active object: it is programmedthrough a library class such as : • class REPEATABLE feature • setup do end • step do end • over :BOOLEAN • tear_downdo end • live • do • fromsetup untilover loopstep end • tear_down • end • end • end
(D) What the wait rule means • Beat enemy number one in concurrent world: atomicity violations • Data races • Illegal interleaving of calls • Data races cannot occur in SCOOP
Semantics vs implementation • Older SCOOP literature says that feature application “waits” until all the separate arguments’ handlers are available • This is not necessary! • What matters is exclusive access: implementation does not have to wait unless semantically necessary • The implementation performs some of these optimizations f (a, b, c:separateT) do something_else ar bs end No need to wait for a and b until here No need to wait for c!
(D) Wait rule A routine call guarantees exclusive access to the handlers (the processors) of all separate arguments some_routine(nonsep_a, nonsep_b, sep_c, sep_d, sep_e) Exclusive access to sep_c, sep_d, sep_ewithin a_routine
(E) Resynchronization: lazywait (Caromel) • How do we resynchronize after asynchronous (separate) call? • No explicit mechanism! • The client will wait when, and only when, it needs to: xf xg (a) yf … value :=x.some_query • Lazy wait (also known as wait by necessity) Wait here! Reasonability
(E) Synchronyvsasynchronyrevisited • For a separate target x: • x command (...) is asynchronous • v := x query (...) is synchronous
(F) Contracts What becomes of contracts, in particular preconditions, in a concurrent context?
Preconditions as wait conditions • if acc1balance >= 100 then transfer (acc1, acc2, 100) end • if acc1balance >= 100 then transfer (acc1, acc3, 100) end • transfer (source, target: ACCOUNT; • amount: INTEGER) • -- Transfer amount from source to target. • require • sourcebalance >= amount • do • sourcewithdraw (amount) • targetdeposit (amount) • ensure • sourcebalance = old sourcebalance – amount • targetbalance = old targetbalance + amount • end separate
(F) Contracts put (b:separate QUEUE [INTEGER ] ; v : INTEGER) -- Storevinto buffer b. require notb.is_full i> 0 do b.put(i) ensure notb.is_empty end ... put (my_buffer, 10 ) Precondition becomes wait condition