Coordination aspect Review of AOP Summary of threads

  • Slides: 45
Download presentation
Coordination aspect • Review of AOP • Summary of threads in Java • COOL

Coordination aspect • Review of AOP • Summary of threads in Java • COOL (COOrdination Language) – Design decisions – Implementation at Xerox PARC and for Demeter/Java 1/31/2022 AOO / Demeter / NU 1

“To my taste the main characteristic of intelligent thinking is that one is willing

“To my taste the main characteristic of intelligent thinking is that one is willing and able to study in depth an aspect of one's subject matter in isolation, for the sake of its own consistency, all the time knowing that one is occupying oneself with only one of the aspects. . Quote taken from Gregor Kiczales’ talk: www. parc. xerox. com/aop - Dijkstra, A discipline of programming, 1976 last chapter, In retrospect 1/31/2022 AOO / Demeter / NU 2

A few more viewgraphs taken from Gregor Kiczales’ talk www. parc. xerox. com/aop 1/31/2022

A few more viewgraphs taken from Gregor Kiczales’ talk www. parc. xerox. com/aop 1/31/2022 AOO / Demeter / NU 3

the goal is a clear separation of concerns we want: – natural decomposition –

the goal is a clear separation of concerns we want: – natural decomposition – concerns to be cleanly localized – handling of them to be explicit – in both design and implementation 1/31/2022 AOO / Demeter / NU 4

achieving this requires. . . • synergy among – problem structure and – design

achieving this requires. . . • synergy among – problem structure and – design concepts and – language mechanisms “natural design” “the program looks like the design” 1/31/2022 AOO / Demeter / NU 5

Cross-cutting of components and aspects better program ordinary program structure-shy functionality structure synchronization 1/31/2022

Cross-cutting of components and aspects better program ordinary program structure-shy functionality structure synchronization 1/31/2022 AOO / Demeter / NU Components Aspect 1 Aspect 2 6

Demeter structure-shy behavior structure-shy communication compiler/ weaver synchronization 1/31/2022 AOO / Demeter / NU

Demeter structure-shy behavior structure-shy communication compiler/ weaver synchronization 1/31/2022 AOO / Demeter / NU structure-shy object description 7

Aspect-Oriented Programming components and aspect descriptions High-level view, implementation may be different Source Code

Aspect-Oriented Programming components and aspect descriptions High-level view, implementation may be different Source Code (tangled code) weaver (compiletime) 1/31/2022 AOO / Demeter / NU 8

Technology Evolution Object-Oriented Programming Law of Demeter dilemma Tangled structure/behavior Adaptive Programming Other tangled

Technology Evolution Object-Oriented Programming Law of Demeter dilemma Tangled structure/behavior Adaptive Programming Other tangled code Aspect-Oriented Programming 1/31/2022 AOO / Demeter / NU 9

Components/Aspects of Demeter • Functionality (structure-shy) – Traversal (Traversal Strategies) – Functionality Modification (Visitors)

Components/Aspects of Demeter • Functionality (structure-shy) – Traversal (Traversal Strategies) – Functionality Modification (Visitors) • Structure (UML class diagrams) • Description (annotated UML class diagrams, class dictionaries) • Synchronization 1/31/2022 AOO / Demeter / NU 10

Threads ! Thread 1 1/31/2022 AOO / Demeter / NU Thread 2 11

Threads ! Thread 1 1/31/2022 AOO / Demeter / NU Thread 2 11

Coordination aspect • Put coordination code about thread synchronization in one place. • Threads

Coordination aspect • Put coordination code about thread synchronization in one place. • Threads are synchronized through methods. • Method synchronization – Exclusion sets – Method managers 1/31/2022 AOO / Demeter / NU 12

Java Threads • Thread class in Standard Java libraries • Thread worker = new

Java Threads • Thread class in Standard Java libraries • Thread worker = new Thread() • start method spawns a new thread of control based on Thread object. start invokes the threads run method: active thread 1/31/2022 AOO / Demeter / NU 13

Java Threads • synchronized method: locks object. A thread invoking a synchronized method on

Java Threads • synchronized method: locks object. A thread invoking a synchronized method on the same object must wait until lock released. Mutual exclusion of two threads. class Account { synchronized double get. Balance() { return balance; } synchronized void deposit(double a) { balance += a; } } 1/31/2022 AOO / Demeter / NU 14

Java Threads • synchronized statements synchronized (expr) statement • lock an object without invoking

Java Threads • synchronized statements synchronized (expr) statement • lock an object without invoking a synchronized method • expr must produce an object to lock 1/31/2022 AOO / Demeter / NU 15

Java Threads • communication between threads with wait and notify (defined in class Object).

Java Threads • communication between threads with wait and notify (defined in class Object). • cliché: synchronized void do. When. Condition() { while (!condition) wait(); do_it(); } 1/31/2022 AOO / Demeter / NU 16

Java Threads • notify: after change of data that some other thread is waiting

Java Threads • notify: after change of data that some other thread is waiting on synchronized void change. Condition(){ // change some value notifyall(); // wakes all waiting threads } 1/31/2022 AOO / Demeter / NU 17

Problem with synchronization code: it is tangled with component code class Bounded. Buffer {

Problem with synchronization code: it is tangled with component code class Bounded. Buffer { Object[] array; int put. Ptr = 0, take. Ptr = 0; int used. Slots = 0; Bounded. Buffer(int capacity){ array = new Object[capacity]; } 1/31/2022 AOO / Demeter / NU 18

Tangling synchronized void put(Object o) { while (used. Slots == array. length) { try

Tangling synchronized void put(Object o) { while (used. Slots == array. length) { try { wait(); } catch (Interrupted. Exception e) {}; } array[put. Ptr] = o; put. Ptr = (put. Ptr +1 ) % array. length; if (used. Slots==0) notifyall(); used. Slots++; // if (used. Slots++==0) notifyall(); } 1/31/2022 AOO / Demeter / NU 19

Solution: tease apart basics and synchronization • write core behavior of buffer • write

Solution: tease apart basics and synchronization • write core behavior of buffer • write coordinator which deals with synchronization • use weaver which combines them together • simpler code • replace synchronized, wait, notify and notifyall by coordinators 1/31/2022 AOO / Demeter / NU 20

Using Demeter/Java, *. beh file With coordinator: basics Bounded. Buffer { public void put

Using Demeter/Java, *. beh file With coordinator: basics Bounded. Buffer { public void put (Object o) (@ array[put. Ptr] = o; put. Ptr = (put. Ptr+1)%array. length; used. Slots++; @) public Object take() (@ Object old = array[take. Ptr]; array[take. Ptr] = null; take. Ptr = (take. Ptr+1)%array. length; used. Slots--; return old; @) 1/31/2022 AOO / Demeter / NU 21

Using Demeter/COOL, put into *. cool file Coordinator coordinator Bounded. Buffer { selfex put,

Using Demeter/COOL, put into *. cool file Coordinator coordinator Bounded. Buffer { selfex put, take; exclusion sets mutex {put, take} condition empty=true, full=false; coordinator variables 1/31/2022 AOO / Demeter / NU 22

Coordinator method managers with requires clauses and entry/exit clauses put requires (!full) { on

Coordinator method managers with requires clauses and entry/exit clauses put requires (!full) { on exit {empty=false; if (used. Slots==array. length) full=true; }} take requires (!empty) { on exit {full=false; if (used. Slots==0) empty=true; }} } 1/31/2022 AOO / Demeter / NU 23

exclusion sets • selfex A. f, B. g; – only one thread can call

exclusion sets • selfex A. f, B. g; – only one thread can call a selfex method – A. f and B. g may run simultaneously. • mutex {g, h, i} mutex {f, k, l} – if a thread calls a method in a mutex set, no other thread may call a method in the same mutex set. 1/31/2022 AOO / Demeter / NU 24

Multi-class coordination supported coordinator A, B { selfex A. put, B. take; mutex {B.

Multi-class coordination supported coordinator A, B { selfex A. put, B. take; mutex {B. put, A. take} condition empty=true, full=false; . . . 1/31/2022 AOO / Demeter / NU 25

Design decisions behind COOL • The smallest unit of synchronization is the method. •

Design decisions behind COOL • The smallest unit of synchronization is the method. • The provider of a service defines the synchronization (monitor approach). • Coordination is contained within one coordinator. • Association from object to coordinator is static. 1/31/2022 AOO / Demeter / NU 26

Design decisions behind COOL • Deals with thread synchronization within each execution space. No

Design decisions behind COOL • Deals with thread synchronization within each execution space. No distributed synchronization. • Coordinators can access the objects’ state, but they can only modify their own state. Synchronization does not “disturb” objects. Currently a design rule not checked by implementation. 1/31/2022 AOO / Demeter / NU 27

COOL • Provides means for dealing with mutual exclusion of threads, synchronization state, guarded

COOL • Provides means for dealing with mutual exclusion of threads, synchronization state, guarded suspension and notification ! Thread 1 Thread 2 coordinator 1/31/2022 AOO / Demeter / NU 28

COOL • Identifies “good” abstractions for coordinating the execution of OO programs – coordination,

COOL • Identifies “good” abstractions for coordinating the execution of OO programs – coordination, not modification of the objects – mutual exclusion: sets of methods – preconditions on methods – coordination state (history-sensitive schemes) – state transitions on coordination 1/31/2022 AOO / Demeter / NU 29

plain Java public class Shape { protected double x_ = 0. 0; y_ =

plain Java public class Shape { protected double x_ = 0. 0; y_ = 0. 0; width_ = 0. 0; height_ = 0. 0; double x() { return x_(); } double y() { return y_(); } double width(){ return width_(); } double height(){ return height_(); } COOL Shape coordinator Shape { selfex {adjust. Location, adjust. Dimensions} mutex {adjust. Location, x} mutex {adjust. Location, y} mutex {adjust. Dimensions, width} mutex {adjust. Dimensions, height} } void adjust. Location() { x_ = long. Calculation 1(); y_ = long. Calculation 2(); } void adjust. Dimensions() { width_ = long. Calculation 3(); height_ = long. Calculation 4(); } } 1/31/2022 AOO / Demeter / NU 30

Programming with COOL Protocol object/coordinator: coordinator 3 7 2 4 6 8 1 5

Programming with COOL Protocol object/coordinator: coordinator 3 7 2 4 6 8 1 5 m() {…} object 1/31/2022 1: method invocation 2: request presented to the coordinator 3: coordinator checks synchronization state, eventually suspending thread; when thread can proceed, coordinator performs “on_entry” actions 4: request proceeds to the object 5: method execution 6: return is presented to coordinator 7: coordinator performs “on_exit” actions AOO / Demeter / NU 31 8: method returns

COOL View of Classes • Stronger visibility: – coordinator can access: • all methods

COOL View of Classes • Stronger visibility: – coordinator can access: • all methods and variables of its classes, independent of access control • all non-private methods and variables of their superclasses • Limited actions: – only read variables, not modify them – only coordinate methods, not invoke them 1/31/2022 AOO / Demeter / NU 32

Xerox PARC Implemention Implementing COOL Programming with COOL coordinator object coordinator 3 1 33

Xerox PARC Implemention Implementing COOL Programming with COOL coordinator object coordinator 3 1 33 7 2 4 6 8 5 m() {…} 1 object Implementation Semantics 1/31/2022 7 AOO / Demeter / NU 33

COOL public class Bounded. Buffer { private Object array[]; private int put. Ptr =

COOL public class Bounded. Buffer { private Object array[]; private int put. Ptr = 0, take. Ptr = 0; private int used. Slots = 0; public Bounded. Buffer(int capcty){ array = new Object[capcty]; } public void put(Object o) { array[put. Ptr] = o; put. Ptr = (put. Ptr+1)%array. length; used. Slots++; } public Object take() { Object old = array[take. Ptr]; array[take. Ptr] = null; take. Ptr = (take. Ptr+1)%array. length; used. Slots--; return old; } } 1/31/2022 coordinator Bounded. Buffer { selfex {put, take} mutex {put, take}; boolean full=(@ false @), empty=(@ true @); put requires (@ !full @) { on exit (@ empty = false; if (used. Slots==array. length) full = true; @) } take requires (!empty){ on exit (@ full = false; if (used. Slots == 0) empty = true; @) } } AOO / Demeter / NU 34

Implementing COOL Bounded. Buffer. Coord _dcoord // rest of the variables protected void _d_put(Object

Implementing COOL Bounded. Buffer. Coord _dcoord // rest of the variables protected void _d_put(Object o){ //implementation code 2 } 5 public void put(Object o) { _dcoord. enter_put(this); try { _d_put(o); } 6 1 finally { _dcoord. exit_put(this); } } protected Object _d_take() { //implementation code } public Object take() { //similar to put } 1/31/2022 4 8 // variable next page synchronized void enter_put(Bounded. Buffer o){ //. . . 3 } synchronized void exit_put(Bounded. Buffer o) { //. . . 7 } synchronized void enter_take(Bounded. Buffer o){ //. . . } synchronized void exit_take(Bounded. Buffer o) { //. . . } AOO / Demeter / NU 35

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots()==o. _dget_size()) full=true; notify. All(); }. . . 1/31/2022 AOO / Demeter / NU 36

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; to keep track of method execution state public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots() == o. _dget_size()) full = true; notify. All(); } 1/31/2022 AOO / Demeter / NU 37. . .

One class to support COOL class Method. State { int depth = 0; Vector

One class to support COOL class Method. State { int depth = 0; Vector t 1 = new Vector(); final public boolean is. Busy. By. Other() { if (depth > 0 && !t 1. contains(Thread. current. Thread())) return true; else return false; } final public void in() { depth++; t 1. add. Element(Thread. current. Thread()); } final public void out() { depth--; …} 1/31/2022 AOO / Demeter / NU 38

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; coordination vars public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots()==o. _dget_size()) full=true; notify. All(); }. . . 1/31/2022 AOO / Demeter / NU 39

class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State

class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; Implementing COOL public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} conditions for waiting } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots() == o. _dget_size()) full = true; notify. All(); }. . . 1/31/2022 AOO / Demeter / NU 40

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); update method state } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots() == o. _dget_size()) full = true; notify. All(); }. . . 1/31/2022 AOO / Demeter / NU 41

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; update method state if (o. _dget_usedlots() == o. _dget_size()) full = true; notify. All(); }. . . 1/31/2022 AOO / Demeter / NU 42

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); on_exit statements empty = false; if (o. _dget_usedlots()==o. _dget_size()) full=true; notify. All(); } 1/31/2022 AOO / Demeter / NU 43. . .

class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State

class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; Implementing COOL public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots()==o. _dget_size()) full=true; notify. All(); notify state change }. . . 1/31/2022 AOO / Demeter / NU 44

Acknowledgments • Many of the viewgraphs prepared by Crista Lopes for her Ph. D.

Acknowledgments • Many of the viewgraphs prepared by Crista Lopes for her Ph. D. work supported by Xerox PARC. • Implementation of COOL for Demeter/Java by Josh Marshall. Integration into Demeter/Java with Doug Orleans. • ECOOP ‘ 94 paper on synchronization patterns by Lopes/Lieberherr. 1/31/2022 AOO / Demeter / NU 45