Post on 22-Dec-2015
Ownership Types for Object Encapsulation
Authors: Chandrasekhar Boyapati
Barbara Liskov
Liuba Shrira
Presented by: Charles Lin
Course: CMSC 631
A brief digression: const
Consider the following C++ code:
Produces following errors:
class Foo { int x ; int go( const Bar & bar ) const { x = bar.mutate() ; } }
foo.cpp: In method `void Foo::foo(const Bar &) const':
foo.cpp:20: passing `const Bar' as `this' argument of
`int Bar::mutate()' discards qualifiers
foo.cpp:20: assignment of member `Foo::x' in
read-only structure
The burden of annotation
Given const errors, what might a programmer do?
const tells compiler that an object is not mutated
Programmers may ignore this: bad!
Even if programmers don’t need to do much annotation, they must know what to do
Modular reasoning
Want to reason about programs to perform updates
Want to reason on individual modules (e.g., a Java file)
Want to avoid interference from objects in other modules (e.g., by object encapsulation)
Encapsulation
Goal of encapsulation is to hide implementation
private hides implementation…or does it? class Foo {
private Bar b ;
public Bar getBar() {
return b ; // leaks out private data member
}
}
Object Encapsulation
Want to enforce encapsulation, i.e., can’t directly access encapsulated objects
Consider Set class, implemented with ArrayList.
arrListarrList ~~~~setset oo
“depends on”:Criteria for Encapsulation
Objects often contain subobjects
Object x depends on subobject s if mutations of s affect invariants of x
Thus, s should encapsulate x
Example: Set
Set should encapsulate ArrayList If set elements are immutable, then Set
doesn’t have to encapsulate elements.
setsetarrListarrList
aa bb cc dd
Problem with Encapsulation
Iterators need access to internal representation of object
setsetarrListarrList
iteriter
Solution: only allow violations within same module (e.g., Java inner classes)
Solution: Ownership Types
Allows programmer to declare owners of objects
If v is owner of s, then outside objects can not access s, except possibly through v
Want to do this check statically
Rules for Ownership Types
Every object has a (single) owner
The owner can be another object or world
The owner of an object does not change over time
The ownership relation forms a tree rooted at world
Diagram of Ownership Tree
Note: ownership is not transitive. o1 owns o2, but o1 does not own o3
worldworld
o1o1
o2o2
o3o3
o4o4o5o5
o6o6
o7o7
What Can Objects Access?
Itself and objects it owns
Its ancestors in the ownership tree, and objects they own
Anything owned by world (recall, no transitivity of ownership)
How to Annotate
class TStack<stackOwner, TOwner> { TNode<this, TOwner> head ; }// Nodes in stack class TNode<nodeOwner, TOwner> { TNode<nodeOwner, TOwner> next ; T<TOwner> value ;}// Dataclass T<TOwner> {...}
What does annotation mean?
Syntax looks like templates, but contains ownership types instead
First parameter is “real” owner. Remaining parameters pass ownership types to subobjects
Rule:
Object<o1, o2, … on>
o1 <= oi, for 1 < i <= n where x <= y means x is descendant of y in
ownership tree
Example: TStack
TStackTStack
TNodeTNode
TT
ClientClient
worldworld
Inner Classes: Handling Iterators
Allow inner classes to break encapsulation
Inner classes have type annotations just like outer classes
Inner classes do not “inherit” type annotations from outer class
Methods can have ownership types
Allows wrapper objects to have “freer” ownership types than objects they wrap.
See example with elements() method class TStack<stackOwner, TOwner> {
TStackEnum<enumOwner, TOwner>
elements<enumOwner> ()
where (enumOwner <= TOwner) {…}
..}
Encapsulation Theorem
x can access an object owned by o only if (x <= o) or
x is an inner class of object o
Proof is due to restrictions placed on ownership type parameter list
Type Rules
The proof is left to the interested reader
Applications
Upgrades in persistent object stores TF(x) only accesses objects owned by x
Controlling aliasing
Data races
Extension: ownership types combined with region types
Key people in Ownership Types
Chandrasekhar Boyapatiwww.eecs.umich.edu/~bchandra
Dave Clarkewww.cs.uu.nl/people/dave
Thoughts
Annotation Burden? (System uses type inferencing, but still requires 1 in 30 lines must be annotated)
Copy constructors? Can one object access subobjects of the same type?
What if we don’t care about encapsulation everywhere?
Seems simple…why are type rules complex?
Conclusion
Ownership types aren’t magic. As with any type system, you must apply them so they are useful.
In particular, you must determine the “depends on” relation to apply ownership correctly.