4.3 Reference count

A reference count is a counter that is associated with a ThisIsA so that it knows how many WhereIs are pointing at it. When a ThisIsA is not longer pointed to by any WhereIs, then it can be deallocated.

Listing 3 is the revised code to maintain and make use of the referenc count.


Listing 3:WhereIs.03
 
1class CheckMemLeak 
2{ 
3}; 
4 
5class PayLoadType 
6{ 
7    int x; 
8  public: 
9    void setx(int v) { x = v; } 
10    int getx(void) { return x; } 
11}; 
12 
13 
14template <class T> 
15class WhereIs 
16{ 
17  // private section of WhereIs 
18    class ThisIsA 
19    { 
20      // private section of ThisIsA 
21        T payload; 
22        unsigned refCount; 
23      public: 
24        void incRefCount(void) { ++refCount; } 
25        void decRefCount(void) { --refCount; } 
26        bool zeroRefCount(void) { return refCount == 0; } 
27        T &getPayload(void) { return payload; } 
28        ThisIsA(const T &original):payload(original),refCount(0) {} 
29        ThisIsA(void):refCount(0) {} 
30    }; 
31    ThisIsA *ptr; 
32    void nuke(void) { delete ptr; ptr = 0; } 
33  public: 
34    WhereIs(void):ptr(0) {} 
35    WhereIs(const WhereIs<T> &other):ptr(other.ptr) {} 
36    ~WhereIs(void) 
37    { 
38      if (ptr) throw CheckMemLeak(); 
39    } 
40    T & operator*(void) { return ptr->getPayload(); } 
41    void allocate(void) 
42    { 
43      if (ptr) throw CheckMemLeak(); 
44      ptr = new ThisIsA; 
45      ptr->incRefCount(); 
46    } 
47    void allocate(const T &original) 
48    { 
49      if (ptr) throw CheckMemLeak(); 
50      ptr = new ThisIsA(original); 
51      ptr->incRefCount(); 
52    } 
53    void becomesAliasOf(const WhereIs<T> &other) 
54    { 
55      if (ptr) throw CheckMemLeak(); 
56      ptr = other.ptr; 
57      ptr->incRefCount(); 
58    } 
59    void detach(void) 
60    { 
61      if (ptr) 
62      { 
63        ptr->decRefCount(); 
64        if (ptr->zeroRefCount()) 
65        { 
66          nuke(); 
67        } 
68      } 
69      ptr = 0; 
70    } 
71    bool isNull(void) const { return ptr == 0; } 
72}; 
73 
74void test(void) 
75{ 
76  WhereIs<PayLoadType> v,w; 
77  w.allocate(); 
78  (*w).setx(30); 
79  v.becomesAliasOf(w); 
80}

First, nuke becomes private. This is because there should not be any need to explicitly deallocate a ThisIsA. Next, detach is enhaneced to first decrement the reference count of a ThisIsA. If the reference count decrements to 0, then the ThisIsA is deallocated by calling nuke.