Fixed problem with copy constructor
[dyninst.git] / pdutil / h / refCounter.h
1 // refCounter.h
2 // Ariel Tamches
3
4 #ifndef _REF_COUNTER_H_
5 #define _REF_COUNTER_H_
6
7 #pragma interface
8
9 #include <assert.h>
10
11 template <class T>
12 class refCounter {
13  private:
14    class actualData {
15     private:
16       mutable unsigned refCount;
17       T data;
18     public:
19       actualData(const T &src) : data(src) {refCount=0;}
20      ~actualData() {}
21       void reference() const {refCount++;}
22       bool dereference() const {
23          assert(refCount > 0);
24          return (--refCount == 0);
25       }
26       T &getData() {return data;}
27       const T &getData() const {return data;}
28    };
29    actualData *theData;
30       // allocated with new, but not necessarily by us.  _Never_ NULL.
31
32  private:
33    void reference() const {
34       assert(theData);
35       theData->reference();
36    }
37    void dereference() const {
38       assert(theData);
39       if (theData->dereference())
40          delete theData;
41    }
42    refCounter(); // explicitly disallowed
43
44  public:
45    refCounter(const T &src) {
46       // examples:
47       // T y; (y is initialized somehow...)
48       // refCounter<T> x = y; or
49       // refCounter<T> x(y);
50       theData = new actualData(src);
51       assert(theData);
52       reference();
53    }
54    refCounter(const refCounter &src) {
55       // This constructor is what this whole class revolves around.  It's fast.
56       // examples:
57       // refCounter<T> y; (y is initialized somehow...)
58       // refCounter<T> x = y; or
59       // refCounter<T> x(y);
60       src.reference(); // just bumps up a ref count --> fast
61       theData = src.theData;  // just a ptr assignment --> fast
62    }
63   ~refCounter() {
64       dereference();
65    }
66    refCounter &operator=(const refCounter &src) {
67       if (this == &src)
68          return *this; // protect against x=x
69
70       if (theData) {
71         // dereference what we were using...
72         dereference();
73       }
74
75       // ...and attach to the new stuff efficiently
76       theData = src.theData; // just a ptr assignment --> fast
77       reference();           // just bumps a ref cnt  --> fast
78       return *this;
79    }
80    refCounter &operator=(const T &src) {
81       dereference();
82       theData = new actualData(src);
83       reference();
84       return *this;
85    }
86    T &getData() {
87       assert(theData);
88       return theData->getData();
89    }
90    const T &getData() const {
91       assert(theData);
92       return theData->getData();
93    }
94 };
95
96 #endif