Download presentation
Presentation is loading. Please wait.
1
Ownership Types for Object Encapsulation Barbara Liskov Chandrasekhar Boyapati Liuba Shrira Laboratory for Computer Science Massachusetts Institute of Technology {liskov, chandra, liuba}@lcs.mit.edu
2
Outline Object Encapsulation Object Encapsulation Ownership Types Ownership Types Upgrades in Persistent Object Stores Upgrades in Persistent Object Stores
3
Modular Reasoning Goal is local reasoning about correctness Goal is local reasoning about correctness Prove a class meets its specification, using only specifications but not code of other classes Crucial when dealing with large programs Crucial when dealing with large programs Requires no interference from code outside the class Requires no interference from code outside the class Objects must be encapsulated
4
Consider a Set object s implemented using a Vector object v Consider a Set object s implemented using a Vector object v Object Encapsulation v ~ ~ so Local reasoning about s is possible Local reasoning about s is possible If objects outside s do not access v That is, if v is encapsulated within s
5
Encapsulation In general, all objects that s depends on must be encapsulated within s In general, all objects that s depends on must be encapsulated within s s depends on x if mutations of x affect behavior of s s depends on x if mutations of x affect behavior of s Leino, Nelson ( SCR ’00 ) Detlefs, Leino, Nelson ( SRC ’98 )
6
Examples Rep invariant for Set: no-dups Rep invariant for Set: no-dups Then, size of vector is size of set Then, remove stops at match Clearly, v must be inside s Clearly, v must be inside s s v
7
Examples What does no-dups mean? What does no-dups mean? ! e1.equals(e2), for any elements e1 & e2 So set does not depend on elements if elements are immutable So set does not depend on elements if elements are immutable s v
8
Iterators and Encapsulation Iterators require access to representation Iterators require access to representation Okay if violations of encapsulation limited to the same module Okay if violations of encapsulation limited to the same module s v i
9
Ownership Types Goal is to enforce encapsulation statically Goal is to enforce encapsulation statically s v Programmer can declare s owns v Programmer can declare s owns v System ensures v is encapsulated in s System ensures v is encapsulated in s
10
Ownership Types Every object has an owner Every object has an owner Owner can be another object or world Owner can be another object or world Ownership relation forms a tree Ownership relation forms a tree Owner of an object cannot change Owner of an object cannot change world
11
Ownership Types for Encapsulation If an object owns objects it depends on If an object owns objects it depends on Then type system enforces encapsulation Then type system enforces encapsulation If v is inside s and o is outside Then o cannot access v v ~ ~ so
12
Ownership Types world
13
class TStack { TNode head; TNode head; void push(T value) {…} void push(T value) {…} T pop() {…} T pop() {…}} class TNode { TNode next; TNode next; T value; T value; …} class T {…} TStack Example (No Owners) value next head value next value next … … … TStack TNode T
14
TStack Example (With Owners) class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head;} class TNode nodeOwner, TOwner { TNode nodeOwner, TOwner next; TNode nodeOwner, TOwner next; T TOwner value; T TOwner value;} class T TOwner {…} TStack TNode T Classes are parameterized with owners
15
TStack Example class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head;} class TNode nodeOwner, TOwner { TNode nodeOwner, TOwner next; TNode nodeOwner, TOwner next; T TOwner value; T TOwner value;} class T TOwner {…} TStack TNode T First owner owns the “this” object
16
TStack Example class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head;} class TNode nodeOwner, TOwner { TNode nodeOwner, TOwner next; TNode nodeOwner, TOwner next; T TOwner value; T TOwner value;} class T TOwner {…} TStack TNode T TStack owns the “head” TNode
17
TStack Example class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head;} class TNode nodeOwner, TOwner { TNode nodeOwner, TOwner next; TNode nodeOwner, TOwner next; T TOwner value; T TOwner value;} class T TOwner {…} TStack TNode T The “next” TNode has the same owner as the “this” TNode All TNodes have the same owner
18
TStack Example class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head;} class TNode nodeOwner, TOwner { TNode nodeOwner, TOwner next; TNode nodeOwner, TOwner next; T TOwner value; T TOwner value;} class Client clientOwner { TStack this, this s1; TStack this, this s1; TStack this, world s2; TStack this, world s2; TStack world, world s3; TStack world, world s3;} TStack TNode T s1 is an encapsulated stack with encapsulated elements Client
19
TStack Example class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head;} class TNode nodeOwner, TOwner { TNode nodeOwner, TOwner next; TNode nodeOwner, TOwner next; T TOwner value; T TOwner value;} class Client clientOwner { TStack this, this s1; TStack this, this s1; TStack this, world s2; TStack this, world s2; TStack world, world s3; TStack world, world s3;} TStack TNode T s2 is an encapsulated stack with public elements Client world
20
TStack Example class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head;} class TNode nodeOwner, TOwner { TNode nodeOwner, TOwner next; TNode nodeOwner, TOwner next; T TOwner value; T TOwner value;} class Client clientOwner { TStack this, this s1; TStack this, this s1; TStack this, world s2; TStack this, world s2; TStack world, world s3; TStack world, world s3;} TStack TNode T s3 is a public stack with public elements world
21
TStack Example class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head;} class TNode nodeOwner, TOwner { TNode nodeOwner, TOwner next; TNode nodeOwner, TOwner next; T TOwner value; T TOwner value;} class Client clientOwner { TStack this, this s1; TStack this, this s1; TStack this, world s2; TStack this, world s2; TStack world, world s3; TStack world, world s3; TStack world, this s4; // illegal TStack world, this s4; // illegal} TStack TNode T Other owners must be same as or more public than first owner [CD02] This constraint is necessary to enforce encapsulation with subtyping
22
class Client cOwner, sOwner, tOwner where (sOwner <= tOwner) { … TStack sOwner, tOwner head; TStack sOwner, tOwner head;} Constraints on Owners Programmers can constrain owners using where clauses This is legal only if tOwner is same as or more public than sOwner
23
Iterators Consider an Iterator i over Stack s Consider an Iterator i over Stack s If i is encapsulated within s If i is encapsulated within s Then i cannot be used outside s If i is not encapsulated within s If i is not encapsulated within s Then i cannot access representation of s TStack TStackEnum
24
Solution Use inner classes Use inner classes Gives desired access to representation Gives desired access to representation Yet, satisfies our modularity goal Yet, satisfies our modularity goal
25
class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head; …. …. class TStackEnum enumOwner, TOwner implements class TStackEnum enumOwner, TOwner implements TEnum enumOwner, TOwner { TEnum enumOwner, TOwner { TNode TStack.this, TOwner current = TStack.this.head; TNode TStack.this, TOwner current = TStack.this.head; …. …. }} Iterators Inner class objects can access rep of outer class objects TStack TStackEnum
26
class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head; …. …. class TStackEnum enumOwner, TOwner implements class TStackEnum enumOwner, TOwner implements TEnum enumOwner, TOwner {…} TEnum enumOwner, TOwner {…} TStackEnum enumOwner, TOwner elements enumOwner ( ) TStackEnum enumOwner, TOwner elements enumOwner ( ) where (enumOwner <= TOwner) {…} where (enumOwner <= TOwner) {…}} Iterators TStack TStackEnum
27
Ownership Types for Encapsulation If an object owns objects it depends on If an object owns objects it depends on Then type system enforces encapsulation Then type system enforces encapsulation If v is inside s and o is outside Then o cannot access v Unless o is inner class object of s v ~ ~ so
28
class TStack stackOwner, TOwner { TNode this, TOwner head; TNode this, TOwner head; … T TOwner pop() writes (this) { T TOwner pop() writes (this) { if (head == null) return null; if (head == null) return null; T TOwner value = head.value(); T TOwner value = head.value(); head = head.next(); head = head.next(); return value; return value; }} Effects Clauses Methods can specify read and write effects reads(x) means method can read x and its encapsulated objects writes(x) means method can read/write x and its encapsulated objects
29
Related Work Types augmented with owners Types augmented with owners Clarke, Potter, Noble ( OOPSLA ’98 ) Support for subtyping Support for subtyping Clarke, Drossopoulou ( OOPSLA ’02 ) Owners combined with effects clauses Owners combined with effects clauses Boyapati, Rinard ( OOPSLA ’01 )
30
Summary Ownership types capture dependencies Ownership types capture dependencies Extension for inner class objects allows iterators and wrappers Extension for inner class objects allows iterators and wrappers Approach provides expressive power, yet ensures modular reasoning Approach provides expressive power, yet ensures modular reasoning Effects clauses enhance modular reasoning Effects clauses enhance modular reasoning
31
Applications Safe upgrades in persistent object stores Safe upgrades in persistent object stores Preventing data races and deadlocks Preventing data races and deadlocks Boyapati, Lee, Rinard ( OOPSLA ’01 ) ( OOPSLA ’02 ) Safe region-based memory management Safe region-based memory management Boyapati, Salcianu, Beebee, Rinard ( MIT ’02 ) Program understanding Program understanding Aldrich, Kostadinov, Chambers ( OOPSLA ’02 )
32
Upgrades in Persistent Object Stores Persistent Object Stores store objects Persistent Object Stores store objects Persistent Root
33
Upgrades in Persistent Object Stores Objects are accessed within transactions Objects are accessed within transactions Transactions support modular reasoning in spite of concurrency and failures Persistent Root
34
Uses of Upgrades Upgrades are needed to Upgrades are needed to Correct errors Improve performance Meet changing requirements Upgrades can be Upgrades can be Compatible or incompatible Upgrades must be complete Encapsulation enables safe upgrades Encapsulation enables safe upgrades
35
Defining an Upgrade An upgrade is a set of class-upgrades An upgrade is a set of class-upgrades Upgrades must be complete A class upgrade is A class upgrade is old-class, new-class, TF old-class, new-class, TF TF: old-class new-class TF: old-class new-class TF changes representation of objects System preserves identity of objects
36
Executing an Upgrade Requires: transforming all old-class objects Requires: transforming all old-class objects Goal: Don’t interfere with applications Goal: Don’t interfere with applications Don’t stop the world Goal: Be efficient in space and time Goal: Be efficient in space and time Don’t copy the database
37
Solution: Lazy, Just in Time Applications continue to run Applications continue to run Objects are transformed just before first access Objects are transformed just before first access Upgrades can run in parallel Upgrades can run in parallel
38
Desired Semantics Upgrades appear to run when installed Upgrades appear to run when installed Serialized before all later application transactions Upgrades appear to run in upgrade order Upgrades appear to run in upgrade order Within an upgrade, transforms run as if each were the first to run Within an upgrade, transforms run as if each were the first to run
39
Related Work PJama: Atkinson, Dmitriev, Hamilton ( POS ’ 00 ) PJama: Atkinson, Dmitriev, Hamilton ( POS ’ 00 ) Orion: Banerjee, Kim, Kim, Korth ( Sigmod ’ 87 ) Orion: Banerjee, Kim, Kim, Korth ( Sigmod ’ 87 ) O2: Deux et al ( IEEE TKDE ’ 90 ) O2: Deux et al ( IEEE TKDE ’ 90 ) OTGen: Lerner, Habermann ( OOPSLA ’ 90 ) OTGen: Lerner, Habermann ( OOPSLA ’ 90 ) Gemstone: Penney, Stein ( OOPSLA ’ 87 ) Gemstone: Penney, Stein ( OOPSLA ’ 87 )
40
How System Works Objects are transformed just before first access Objects are transformed just before first access Interrupt the application Run earliest pending transform Transform runs in its owns transaction Application continues after transform commits Application continues after transform commits Transforms can be interrupted too Transforms can be interrupted too
41
Example …;U1;A1;TF1(x);A2;… U1 is installed A1 commits A2 accesses x and is interrupted TF1(x) commits A2 commits
42
Example …;U1;A1;TF1(x);A2;… U1 is installed A1 commits A2 accesses x and is interrupted TF1(x) commits A2 commits Suppose A1 modifies z and TF1(x) uses z
43
Example …;U1;A1;TF1(x);A2;TF1(y);A3; … U1 is installed A1 commits A2 accesses x and is interrupted TF1(x) commits A2 commits A3 accesses y and is interrupted TF1(y) commits A3 commits
44
Example …;U1;A1;TF1(x);A2;TF1(y);A3; … U1 is installed A1 commits A2 accesses x and is interrupted TF1(x) commits A2 commits A3 accesses y and is interrupted TF1(y) commits A3 commits Suppose TF1(y) uses x
45
Insuring Correct Behavior S1: TF(x) only accesses objects x owns S1: TF(x) only accesses objects x owns Statically enforced by type system
46
Insuring Correct Behavior S1: TF(x) only accesses objects x owns S1: TF(x) only accesses objects x owns Statically enforced by type system S2: x is transformed before objects x owns S2: x is transformed before objects x owns No access to owned objects from outside Shared access to owned objects from inner class objects (e.g., iterator) s v i
47
Insuring Correct Behavior S1: TF(x) only accesses objects x owns S1: TF(x) only accesses objects x owns S2: x is transformed before objects x owns S2: x is transformed before objects x owns Plus basic lazy scheme Plus basic lazy scheme Applications don’t interfere with transforms Transforms of unrelated objects don’t interfere Transforms of related objects run in proper order (owner before owned)
48
Modular Reasoning S1: TF(x) only accesses objects x owns S1: TF(x) only accesses objects x owns S2: x is transformed before objects x owns S2: x is transformed before objects x owns Plus basic lazy scheme Plus basic lazy scheme Ensures modular reasoning: can reason about TF(x) as an extra method of x’s class Ensures modular reasoning: can reason about TF(x) as an extra method of x’s class
49
Conclusions Modular reasoning is key Modular reasoning is key Ownership types support modular reasoning Ownership types support modular reasoning Software upgrades benefit too Software upgrades benefit too
50
Ownership Types for Object Encapsulation Barbara Liskov Chandrasekhar Boyapati Liuba Shrira Laboratory for Computer Science Massachusetts Institute of Technology {liskov, chandra, liuba}@lcs.mit.edu
51
class IntVector { int size() reads (this) {…} … int size() reads (this) {…} …} class IntStack { IntVector this vec; IntVector this vec; void push(int x) writes (this) {…} … void push(int x) writes (this) {…} …} void m (IntStack s, IntVector v) writes (s) reads (v) where !(v <= s) !(s <= v) { where !(v <= s) !(s <= v) { int n = v.size(); s.push(3); assert( n == v.size() ); int n = v.size(); s.push(3); assert( n == v.size() );} Example of Local Reasoning Is the condition in the assert true?
52
Example of Local Reasoning s is not encapsulated in v, and v is not encapsulated in s class IntVector { int size() reads (this) {…} … int size() reads (this) {…} …} class IntStack { IntVector this vec; IntVector this vec; void push(int x) writes (this) {…} … void push(int x) writes (this) {…} …} void m (IntStack s, IntVector v) writes (s) reads (v) where !(v <= s) !(s <= v) { where !(v <= s) !(s <= v) { int n = v.size(); s.push(3); assert( n == v.size() ); int n = v.size(); s.push(3); assert( n == v.size() );}
53
Example of Local Reasoning size only reads v and its encapsulated objects push only writes s and its encapsulated objects class IntVector { int size() reads (this) {…} … int size() reads (this) {…} …} class IntStack { IntVector this vec; IntVector this vec; void push(int x) writes (this) {…} … void push(int x) writes (this) {…} …} void m (IntStack s, IntVector v) writes (s) reads (v) where !(v <= s) !(s <= v) { where !(v <= s) !(s <= v) { int n = v.size(); s.push(3); assert( n == v.size() ); int n = v.size(); s.push(3); assert( n == v.size() );}
54
Example of Local Reasoning So size and push cannot interfere So the condition in the assert must be true class IntVector { int size() reads (this) {…} … int size() reads (this) {…} …} class IntStack { IntVector this vec; IntVector this vec; void push(int x) writes (this) {…} … void push(int x) writes (this) {…} …} void m (IntStack s, IntVector v) writes (s) reads (v) where !(v <= s) !(s <= v) { where !(v <= s) !(s <= v) { int n = v.size(); s.push(3); assert( n == v.size() ); int n = v.size(); s.push(3); assert( n == v.size() );}
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.