1 / 27

Synthetic OOD concepts and reuse Lecture 4: Separation of concerns

Synthetic OOD concepts and reuse Lecture 4: Separation of concerns. Topics: Complex concern: Memory management Example: Complex operations on composite structures Problem: Memory leaks Solution: Reference counting. Motivation. Suppose we define a function: Expr* mkExpr(void) {

Download Presentation

Synthetic OOD concepts and reuse Lecture 4: Separation of concerns

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Synthetic OOD concepts and reuseLecture 4: Separation of concerns Topics: Complex concern: Memory management Example: Complex operations on composite structures Problem: Memory leaks Solution: Reference counting CSE 335: Software Design

  2. Motivation Suppose we define a function: Expr* mkExpr(void) { Expr* l1 = new Literal(2); Expr* v = new Variable(“x”); Expr* t1 = new Add(l1,v); Expr* l2 = new Literal(2); Expr* t2 = new Multiply(l2,t1); } CSE 335: Software Design

  3. Problem Suppose a client program executes the code: ... Expr* e = mkExpr(); e->print(cout); delete e; ... What happens? How could we ensure that when a composite object is deleted, its parts are also deleted? CSE 335: Software Design

  4. Solution class Expr { ... virtual ~Expr() {} }; class BinaryExpr : public Expr { ... ~BinaryExpr() { delete(leftOperand); delete(rightOperand); } ... }; CSE 335: Software Design

  5. Or is it? Often desirable for two or more composite objects to share the same component Example: Expr* l = new Literal(2); Expr* v = new Variable(“x”); Expr* t1 = new Add(l,v); Expr* t2 = new Multiply(l,t1); Here, object l is the child of two composite objects, t1 and t2. Will our memory-reclamation scheme work now? CSE 335: Software Design

  6. Deleting composites that share parts Not safe for destructor of a composite class to delete its children if these objects might be children of multiple composite objects Solution: design a protocol that tracks references to objects and that deletes an object only when its reference count reaches 0. • Clients never call delete • Objects call delete on themselves! • Clients must explicitly notify objects when references to these objects are assigned or overwritten CSE 335: Software Design

  7. Abstract ref-counting class class RCObject { public: void addRef() { ++refCount; } void removeRef() { if(--refCount <= 0) delete this; } protected: RCObject() : refCount(0) {} virtual ~RCObject() {} private: int refCount; }; CSE 335: Software Design

  8. Example Modify class Expr as follows: class Expr : public RCObject { ... }; Subsequently, every class that derives from Expr will inherit reference counting infra-structure CSE 335: Software Design

  9. Example Modify BinaryExpr as follows: class BinaryExpr : public Expr { ... BinaryExpr( Expr* l, Expr* r ) : leftOperand(l), rightOperand(r) { l->addRef(); r->addRef(); } ... ~BinaryExpr() { l->removeRef(); r->removeRef(); } }; CSE 335: Software Design

  10. Example (continued) Now we write a function that creates an expression: Expr* createExpression(void) { Expr* l = new Literal(2); Expr* v = new Variable(“x”); Expr* t1 = new Add(l,v); Expr* t2 = new Multiply(l,t1); return t2; } Requires client to increment refCount of root object (pointed to here by t2 before it goes out of scope) CSE 335: Software Design

  11. Expr* createExpression(void) { Expr* l = new Literal(2); Expr* v = new Variable(“x”); Expr* t1 = new Add(l,v); Expr* t2 = new Multiply(l,t1); return t2; } Step 1 l : Literal refCount=0 CSE 335: Software Design

  12. Expr* createExpression(void) { Expr* l = new Literal(2); Expr* v = new Variable(“x”); Expr* t1 = new Add(l,v); Expr* t2 = new Multiply(l,t1); return t2; } Step 2 l : Literal refCount=0 v : Variable refCount=0 CSE 335: Software Design

  13. Expr* createExpression(void) { Expr* l = new Literal(2); Expr* v = new Variable(“x”); Expr* t1 = new Add(l,v); Expr* t2 = new Multiply(l,t1); return t2; } Step 3 t1 : Add refCount=0 l : Literal refCount=1 v : Variable refCount=1 CSE 335: Software Design

  14. Expr* createExpression(void) { Expr* l = new Literal(2); Expr* v = new Variable(“x”); Expr* t1 = new Add(l,v); Expr* t2 = new Multiply(l,t1); return t2; } Step 4 t2 : Multiply refCount=0 t1 : Add refCount=1 l : Literal refCount=2 v : Variable refCount=1 CSE 335: Software Design

  15. Example (continued) Client code then uses as follows: ... Expr* e = createExpression(); e->addRef(); // new line e->print(cout); e->removeRef(); // rather than delete(e) ... CSE 335: Software Design

  16. e->addRef(); e->print(cout); e->removeRef(); Adding reference to returned object e t2 : Multiply refCount=1 t1 : Add refCount=1 l : Literal refCount=2 v : Variable refCount=1 CSE 335: Software Design

  17. e->addRef(); e->print(cout); e->removeRef(); Printing expression... e t2 : Multiply refCount=1 t1 : Add refCount=1 l : Literal refCount=2 v : Variable refCount=1 CSE 335: Software Design

  18. e->addRef(); e->print(cout); e->removeRef(); Removing ref: Step 1 e t2 : Multiply refCount=0 t1 : Add refCount=1 l : Literal refCount=1 v : Variable refCount=1 CSE 335: Software Design

  19. e->addRef(); e->print(cout); e->removeRef(); Removing ref: Step 2 e t2 : Multiply refCount=0 t1 : Add refCount=0 l : Literal refCount=1 v : Variable refCount=1 CSE 335: Software Design

  20. e->addRef(); e->print(cout); e->removeRef(); Removing ref: Step 3 e t2 : Multiply refCount=0 t1 : Add refCount=0 l : Literal refCount=0 v : Variable refCount=1 CSE 335: Software Design

  21. e->addRef(); e->print(cout); e->removeRef(); Removing ref: Step 4 e t2 : Multiply refCount=0 t1 : Add refCount=0 l : Literal refCount=0 v : Variable refCount=1 CSE 335: Software Design

  22. e->addRef(); e->print(cout); e->removeRef(); Removing ref: Step 5 e t2 : Multiply refCount=0 t1 : Add refCount=0 v : Variable refCount=0 CSE 335: Software Design

  23. e->addRef(); e->print(cout); e->removeRef(); Removing ref: Step 6 e t2 : Multiply refCount=0 t1 : Add refCount=0 v : Variable refCount=0 CSE 335: Software Design

  24. e->addRef(); e->print(cout); e->removeRef(); Removing ref: Step 7 e t2 : Multiply refCount=0 t1 : Add refCount=0 CSE 335: Software Design

  25. e->addRef(); e->print(cout); e->removeRef(); Removing ref: Step 8 e t2 : Multiply refCount=0 CSE 335: Software Design

  26. Conceptual (but flawed) alternative implementation of createExpression() Expr* createExpression(void) { Expr* l = new Literal(2); l->addRef(); Expr* v = new Variable(“x”); v->addRef(); Expr* t1 = new Add(l,v); t1->addRef(); Expr* t2 = new Multiply(l,t1); t2->addRef(); l->removeRef(); v->removeRef(); t1->removeRef(); t2->removeRef(); // What happens here??? return t2; } CSE 335: Software Design

  27. “Mixin” classes RCObject is an example of a “mixin” class • So-called because designed to encapsulate orthogonal functionality that may be “mixed into” classes in an existing hierarchy • Mixin classes are always abstract • May use multiple inheritance to incorporate functionality in a mixin class if base class does not need it or if base class needs functionality from multiple mixin classes CSE 335: Software Design

More Related