1 / 10

Reference counting, handles and the STL

Reference counting, handles and the STL. Fred Kuhns fredk@cse.wustl.edu Applied Research Laboratory, Department of Computer Science and Engineering, Washington University in St. Louis. Background.

ballard
Download Presentation

Reference counting, handles and the STL

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. Reference counting, handles and the STL Fred Kuhns fredk@cse.wustl.edu Applied Research Laboratory, Department of Computer Science and Engineering, Washington University in St. Louis

  2. Background • In order to take advantage of polymorphism in C++ you must use either pointers or references. • The question of object ownership is critical • Containers own the objects they contain: • copy is made on insertion • object deleted when removed or container deleted • Often you will use Object pointers with STL containers • Consequences: • could make a new object each time it is referenced • make one object, then copy its pointer CSE332: Object Oriented Programming Laboratory

  3. Issues • Object use issues: • is this a const object (all users need read-only access). Then multiple copes or one copy and multiple references is fine • if users alter object then what are the semantics? Should each user have their own copy or is one global object required. • if object is not changed frequently then copy-on-write semantics is viable • efficiency issues: • many copies of an object • creates time and space overhead • how to keep all copies consistent (or knowing if you need to) • One copy with many references: • concurrency control issues • knowing when an object is no longer needed CSE332: Object Oriented Programming Laboratory

  4. Problems and Solutions • context: class hierarchy captures behavioral differences • problem: container is only able to store objects of a specific type • solution: store object references or addresses in containers • context: containers own contained objects • problem: objects are copied causing efficiency problems • solution: store object pointers in containers • context: object pointer appears in many containers. • problem: how do you know when it is safe to delete object • solution: reference counting • context: many references to an object that is infrequently changed. • problem: changes should only be visible to user making the change. • solution: copy-on-write semantics CSE332: Object Oriented Programming Laboratory

  5. A more general observation • “Counted Pointer Idiom”, J.O. Coplien, Advanced C++ - Programming Styles and Idioms • context: memory management of dynamically created objects • pointers are convenient for dynamic structures (trees etc) and for sharing • passing object pointers is efficient • problem: managing object pointers is error prone. • Solution: known by many names - Counted Pointer Idiom (aka Handler idiom); proxy pattern; smart pointers; Handle-Body idiom • Handler can be passed by value • Pointer may be assigned to Handler so when you leave the enclosing scope Handler is destroyed CSE332: Object Oriented Programming Laboratory

  6. Reference Counting Techniques (intrusive) class Handle { public: Handle(…) { body = new Body(…); body->refCount++; } Handle(const Handle& h) { body = h.body; body->refCount++; } Handle& operator=(const Handle& h) { h.body->refCount++; if (--body->refCount <= 0) delete body; body = h.body; return *this; } ~Handle() { if (--body->refCount <= 0) delete body; } Body* operator->() {return body;} private: Body *body; }; class Body { public: void service(); private: friend class Handle; Body( … ) { … } ~Body( … ) { … } int refCount; }; CSE332: Object Oriented Programming Laboratory

  7. Non-Intrusive Example template <class X> class Handle { X* rep; int* pcount; public: Handle() : rep(new X), pcount(new int(1)){} Handle(X* pp): rep(pp), pcount(new int(1)){} Handle(const Handle& r) : rep(r.rep), pcount(r.pcount){*pcount)++;} Handle<X>& operator=(const Handle<X>& r) { if (rep == r.rep) return *this; if(--(*pcount) == 0) { delete rep; delete pcount; } rep = r.rep; pcount = r.pcount; (*pcount)++; return *this; } ~Handle() { if (--(*pcount) == 0) {delete rep; delete pcount;} } X* operator->() {return rep;} }; Can you think of other operators for handler? CSE332: Object Oriented Programming Laboratory

  8. Do a little more • If you need to perform some extra processing on the Body object you may replicate the representation classes interface within the Handle class. • For example, in a multithreaded program (or multi-process with shared memory) you can add locking primitives to the appropriate method calls or member object references. template <class T> class ImplHandler { T* rep; Lock lock; int *pcount; public: void value() {Lock_ptr x(lock); return rep->value();} … }; CSE332: Object Oriented Programming Laboratory

  9. Copy-On-Write Semantics • Use a Handle to reference object • if const object returned then OK • if not const then need to know if user is/will write to the object • overload any and all body member functions that alter the object’s state. operator=() and operator*() are likely candidates CSE332: Object Oriented Programming Laboratory

  10. String Class Example • class String { • private: • class StrRep { • // define how string is stored and managed • … }; • StrRep* *srep_; • public: • class Cref { • friend class String; String& s_; int i_; • Cref(String &s, int i) : s_(s), i_(i) {} • public: • operator char() {return s_.read(i_);} // type conversion • void operator=(char c) {s_.write(i_, c);} // assignment • }; • String& operator=(const String& s) { • s.srep_->ref_++; • if (--srep_->ref_ == 0) delete srep_; • srep_ = s.srep_; return *this; • } • char read(int i) const {return srep_->str_[i];} • void write(int i, char c) • {srep_ = srep_->get_copy(); srep_->str_[i] = c;} • char operator[](int i) const {return srep_->str_[i];} • Cref operator[](int i) {return Cref(*this, 0);} • … }; CSE332: Object Oriented Programming Laboratory

More Related