430 likes | 453 Views
Object-Oriented Software Construction. Bertrand Meyer. Lecture 20: Object-oriented concurrency Piotr Nienaltowski. Overview . A bit of history O-O and concurrency SCOOP model Examples. Sequential programming . Used to be messy It is still hard but: Structured programming
E N D
Object-Oriented Software Construction Bertrand Meyer OOSC Lecture 20 - Concurrency
Lecture 20: Object-oriented concurrencyPiotr Nienaltowski OOSC Lecture 20 - Concurrency
Overview • A bit of history • O-O and concurrency • SCOOP model • Examples OOSC Lecture 20 - Concurrency
Sequential programming • Used to be messy • It is still hard but: • Structured programming • Data abstraction & object technology • Design by Contract • Genericity • Architectural techniques • Switch from operational reasoning to logical deduction (e.g. invariants) OOSC Lecture 20 - Concurrency
Concurrent programming • Used to be messy • And it still is! • Java/C# threading models • No real breakthrough • Only understandable through operational reasoning OOSC Lecture 20 - Concurrency
Impedance mismatch • OO: high-level abstraction mechanisms • Concurrency: very low-level mechanisms • semaphores, locks, critical sections, suspend, … OOSC Lecture 20 - Concurrency
O-O and concurrency • “I don’t understand why objects are non concurrent in the first place” (Robin Milner) • Many attempts, e.g. active objects • Problems: inheritance anomaly • No mechanism widely accepted • In practice, low-level mechanisms on top of O-O language OOSC Lecture 20 - Concurrency
Motivations • Extend object technology with general and powerful concurrency support • Provide the industry with simple techniques for parallel, distributed, Internet, real-time programming • Let programmers sleep better! OOSC Lecture 20 - Concurrency
The SCOOP model • Simple Concurrent Object-Oriented Programming • High-level concurrency mechanism • Fully uses inheritance and other O-O techniques • Applicable to many physical setups: multiprocessing, multithreading, distributed execution, Web services... • Minimal extension of Eiffel • Based on Design by Contract OOSC Lecture 20 - Concurrency
Actions Object-oriented computation Objects Processor To perform a computation is • to apply certain actions • to certain objects • using certain processors. OOSC Lecture 20 - Concurrency
What makes an application concurrent? Processor: autonomous thread of control supporting sequential execution of instructions on one or more objects Can be implemented as: • Process • Thread • current implementation based on .NET threading • AppDomain (.NET) • Web service Actions Objects Processor OOSC Lecture 20 - Concurrency
Handling rule All calls on an object are executed by its processor’s handler OOSC Lecture 20 - Concurrency
Feature call: synchronous x:CLASS_X ... x.f (a) Object 1 Object 2 f (a: A) require a /= Void ensure not a.empty previous_instruction . ( ) x f a next_instruction ( CLASS_T ) (CLASS_ X ) Processor OOSC Lecture 20 - Concurrency
Separate feature call: asynchronous x:separateCLASS_X ... x.f (a) Object 1 Object 2 f (a: A) require a /= Void ensure not a.empty previous_instruction . ( ) x f a next_instruction ( CLASS_T ) (CLASS_ X ) Processor 2 Processor 1 OOSC Lecture 20 - Concurrency
Separateness rule Calls to non-separate objects are synchronous Calls to separate objects are asynchronous OOSC Lecture 20 - Concurrency
Reasoning about objects {Prerand INV} bodyr {POSTrand INV} {Prer’} x.r (a) {POSTr’} Only n proofs for n exported routines! OOSC Lecture 20 - Concurrency
In a concurrent context {Prerand INV} bodyr {POSTrand INV} {Prer’} x.r (a) {POSTr’} Only n proofs for n exported routines? Client 1, r1 Client 3, r3 Client 2, r2 OOSC Lecture 20 - Concurrency
Mutual exclusion rule At most one feature may execute on any one object at any one time OOSC Lecture 20 - Concurrency
Access control policy Target of separate call must be formal argument of enclosing routine: store (buffer:separate BUFFER [INTEGER]; value: INTEGER)is -- Store value into buffer. do buffer.put (value) end Call with separate argument gives exclusive access: store (my_buffer, 10) OOSC Lecture 20 - Concurrency
Contracts in Eiffel store (buffer: BUFFER [INTEGER]; value: INTEGER) is -- Store value into buffer. require not buffer.is_full value > 0 do buffer.put (value) ensure notbuffer.is_empty end ... store (my_buffer, 10) • If b is separate, precondition becomes wait condition (instead of correctness condition) Precondition OOSC Lecture 20 - Concurrency
From preconditions to wait-conditions store (buffer:separate BUFFER [INTEGER]; value: INTEGER) is -- Store value into buffer. require not buffer.is_full value > 0 do buffer.put (value) ensure notbuffer.is_empty end ... store (my_buffer, 10) On separate target, precondition becomes wait condition OOSC Lecture 20 - Concurrency
Wait by necessity • No special mechanism for client to resynchronize with supplier after separate call. • The client will wait only when it needs to: x.f x.g (a) y.f … value := x.some_query Wait here! OOSC Lecture 20 - Concurrency
Duels Problem: Impatient client (challenger) wants to snatch object from another client (holder) • Can’t just interrupt holder, service challenger, and resume holder: would produce inconsistent object. • But: can cause exception, which will be handled safely. OOSC Lecture 20 - Concurrency
Duels OOSC Lecture 20 - Concurrency
Mapping processors to physical resources Concurrency Control File (CCF) create system "palin" (4): "c:\prog\appl1\appl1.exe" "cleese" (2): "c:\prog\appl2\appl2.dll" "Current" (5): "c:\prog\appl3\appl3.dll" end external Database_handler: "jones" port 9000 ATM_handler: "chapman" port 8001 end default port: 8001; instance: 10 end OOSC Lecture 20 - Concurrency
SCOOP platform-independent .NET Compact Framework .NET / ROTOR POSIXThreads … Implementation of SCOOP • Can be implemented on various platforms • Microsoft .NET is our reference platform OOSC Lecture 20 - Concurrency
SCOOPLI: a library for SCOOP • Implemented in Eiffel on .NET • Aim: try out solutions without bothering with compiler issues • Can serve as a basis for compiler implementations OOSC Lecture 20 - Concurrency
Example: Bounded buffers separate class BOUNDED_BUFFER [G] inherit BOUNDED_QUEUE[G] end OOSC Lecture 20 - Concurrency
Example: Bounded buffers class BUFFER_ACCESS [G] feature put (b: BOUNDED_BUFFER [G]; x: G)is -- Insert x into b. require not b.full do b.put (x) ensure not b.empty end OOSC Lecture 20 - Concurrency
Example: Bounded buffers remove (b: BOUNDED_BUFFER [G])is -- Remove an element from b require not b.empty do b.remove ensure not b.full end item (b: BOUNDED_BUFFER [G]): G is -- Oldest element not yet consumed require not b.empty do Result := b.item end end -- classBUFFER_ACCESS [G] OOSC Lecture 20 - Concurrency
Example: Bounded buffers Usage of bounded buffers my_buffer_access: BUFFER_ACCESS [INTEGER] my_bounded_buffer: BOUNDED_BUFFER [INTEGER] createmy_buffer_access createmy_bounded_buffer my_buffer_access.put (my_bounded_buffer, 25) my_buffer_access.put (my_bounded_buffer, 50) my_result := my_buffer_acces.item (my_bounded_buffer) OOSC Lecture 20 - Concurrency
Example: Elevator In order to achieve maximal concurrency, all objects are separate OOSC Lecture 20 - Concurrency
Class BUTTON OOSC Lecture 20 - Concurrency
Class BUTTON separate class BUTTON feature target: INTEGER end -- class BUTTON OOSC Lecture 20 - Concurrency
Class CABIN_BUTTON separate class CABIN_BUTTON inherit BUTTON feature cabin: ELEVATOR request is -- Send to associated elevator a request to stop on level target. do actual_request (cabin) end OOSC Lecture 20 - Concurrency
Class CABIN_BUTTON actual_request (e: ELEVATOR)is -- Get hold of e and send a request to stop on level target. do e.accept (target) end end -- class CABIN_BUTTON OOSC Lecture 20 - Concurrency
Class ELEVATOR separate class ELEVATOR feature {BUTTON, DISPATCHER} accept (floor: INTEGER)is -- Record and process a request to go to floor. do record (floor) if not moving then process_request end end OOSC Lecture 20 - Concurrency
Class ELEVATOR feature {MOTOR} record_stop (floor: INTEGER)is -- Record information that elevator has stopped on the floor. do moving := False position := floor process_request end OOSC Lecture 20 - Concurrency
Class ELEVATOR feature {NONE} process_request is -- Handle next pending request, if any. local floor: INTEGER do if not pending.is_empty then floor := pending.item actual_process (puller, floor) pending.remove end end OOSC Lecture 20 - Concurrency
Class ELEVATOR actual_process (m: MOTOR; floor: INTEGER) is -- Handle next pending request, if any. do moving :=true m.move (floor) end feature {NONE} puller: MOTOR pending: QUEUE [INTEGER] -- Queue of pending requests. end -- class ELEVATOR OOSC Lecture 20 - Concurrency
Class MOTOR separate class MOTOR feature {ELEVATOR} move (floor: INTEGER)is -- Go to floor; once there report. do -- Direct the physical device to move to floor gui_main_window.move_elevator (cabin_number, floor) signal_stopped (cabin) end signal_stopped (e: ELEVATOR)is -- Report that elevator e stopped on level position. do e.record_stop (position) end OOSC Lecture 20 - Concurrency
Class MOTOR feature {NONE} cabin: ELEVATOR position: INTEGER -- Current floor level. gui_main_window: GUI_MAIN_WINDOW end -- class MOTOR OOSC Lecture 20 - Concurrency
Additional information • Nienaltowski P., Arslan V., Meyer B. Concurrent object-oriented programming on .NET, IEE Proceedings Software, Special Issue on ROTOR, October 2003. • Meyer B. Object-Oriented Software Construction, chapter 31, 2nd edition, Prentice Hall, 1997. • Project website http://se.inf.ethz.ch/research/scoop OOSC Lecture 20 - Concurrency