[ fromfile: refcount.xml id: refcount ]
Unlike Java, C++ has no garbage collection.
Garbage collection is a thread that recovers heap memory that is no longer referenced.
It runs when the CPU is relatively idle, or when it is running out of memory.
When an object is created, its reference counter is set to 1.
Each time the object is newly referenced, the reference counter is incremented.
Each time it loses a reference, the reference counter is decremented.
When the reference count becomes 0, the shared object can be deallocated.
To make your own implicitly shared flyweight, you can write your own reference counting code, or reuse two Qt classes: QSharedData and QSharedDataPointer.
QSharedData provides a public QAtomicInt ref
member, for a reference count.
QSharedDataPointer updates the reference count of its shared data depending on whether it is being copied or detached.
This example starts with a relatively mundane, non-sharing MyString
class that implements strings with dynamic arrays of char
, shown in Example 11.15.
Example 11.15. src/mystring/shareddata/mystring.h
#ifndef MYSTRING_H #define MYSTRING_H #include <iostream> class MyString { public: MyString(const MyString& str); MyString& operator=(const MyString& a); MyString(); MyString(const char* chptr); explicit MyString(int size); virtual ~MyString(); friend std::ostream& operator<<(std::ostream& os, const MyString& s); int length() const; MyString& operator+= (const MyString& other); friend MyString operator+(const MyString&, const MyString&); protected: int m_Len; char* m_Buffer; void copy(const char* chptr); }; #endif // #ifndef MYSTRING_H
Example 11.16 extends the MyString
class by adding reference counting capability.
This is the private implementation class.
Example 11.16. src/mystring/shareddata/stringdata.h
[ . . . . ] class StringData : public QSharedData, public MyString { public: friend class SString; StringData() {} StringData(const char* d) : MyString(d) {} explicit StringData(int len) : MyString(len) {} StringData(const StringData& other) : QSharedData(other), MyString(other) {} }; [ . . . . ]
The implicitly shared SString
, shown in Example 11.17, is an example of a class that uses the QSharedDataPointer to achieve copy on write.
Example 11.17. src/mystring/shareddata/sstring.h
[ . . . . ]
class SString {
public:
SString();
explicit SString(int len);
SString(const char* ptr);
SString& operator+= (const SString& other);
int length() const;
int refcount() const {return m_d->ref;}
friend SString operator+(SString, SString);
friend std::ostream& operator<< (std::ostream&, const SString&);
[ . . . . ]
private:
// Private Implementation Pattern
QSharedDataPointer<StringData> m_d;
};
[ . . . . ]
The public methods of SString
delegate to StringData
.
The actual shared data is copied automatically whenever m_d
is dereferenced in a non-const
way.
Example 11.18 demonstrates that the refcount()
decreases when one of the shared flyweights is modified.
Example 11.18. src/mystring/shareddata/sharedmain.cpp
QExplicitlySharedDataPointer is the same as QSharedDataPointer, but you must explicitly call detach()
on the QSharedData each time that a copy is needed.
Most Qt classes implement the Flyweight Pattern, for either implicit sharing, or for other reasons.
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |