1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF)                              */
3 /* (C) Copyright IBM Corp. 2001                                              */
4 /*                                                                           */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0.    */
6 /*****************************************************************************/
7 
8 #ifndef STAF_RefPtr
9 #define STAF_RefPtr
10 
11 #include "STAFThread.h"
12 
13 #ifdef __cplusplus
14 
15 // STAFBuffer<T> - This class provides a simple delete wrapper
16 
17 template <class TheType>
18 class STAFBuffer
19 {
20 public:
21 
22     enum Init { INIT = 0 };
23     enum Type { SCALAR = 0, ARRAY = 1 };
24 
25     STAFBuffer(TheType *, Init init, Type type = ARRAY);
26 
27     TheType *operator->() const { return  fPtr; }
28     TheType &operator*()  const { return *fPtr; }
29     operator TheType *()  const { return  fPtr; }
30 
31     ~STAFBuffer();
32 
33 private:
34 
35     // Don't allow assignment or copy construction
36     STAFBuffer(const STAFBuffer &);
37     STAFBuffer &operator=(const STAFBuffer &from);
38     STAFBuffer &operator=(const TheType *);
39 
40     TheType *fPtr;
41     Type fType;
42 };
43 
44 template <class TheType>
STAFBuffer(TheType * ptr,Init init,Type type)45 inline STAFBuffer<TheType>::STAFBuffer(TheType *ptr, Init init, Type type)
46     : fPtr(ptr), fType(type)
47 {
48     /* Do Nothing */
49 }
50 
51 template <class TheType>
~STAFBuffer()52 inline STAFBuffer<TheType>::~STAFBuffer()
53 {
54     if (fType == SCALAR) delete fPtr;
55     else delete [] fPtr;
56 }
57 
58 
59 // STAFRefPtr<T> - This class provides thread safe reference counted pointers
60 
61 template <class TheType>
62 class STAFRefPtr
63 {
64 public:
65 
66     enum Init { INIT = 0 };
67     enum Type { SCALAR = 0, ARRAY = 1, CUSTOM = 2, CUSTOMARRAY = 3 };
68     typedef void(*TypeFreeFunction)(TheType *);
69     typedef void(*TypeArrayFreeFunction)(TheType *, unsigned int);
70 
71     STAFRefPtr();
72     STAFRefPtr(TheType *, Init init, Type type = SCALAR, TypeFreeFunction = 0);
73     STAFRefPtr(TheType *, Init init, unsigned int size,
74                TypeArrayFreeFunction arrayFreeFunc);
75     STAFRefPtr(const STAFRefPtr &from);
76 
77     STAFRefPtr &operator=(const STAFRefPtr &from);
78     bool operator==(const STAFRefPtr &rhs);
79     TheType *operator->() const { return  fPtr; }
80     TheType &operator*()  const { return *fPtr; }
81     operator TheType *()  const { return  fPtr; }
82 
count()83     STAFThreadSafeScalar_t count() { return fCount ? *fCount : -1; }
84 
85     ~STAFRefPtr();
86 
87 private:
88 
89     // Don't allow assignment from raw pointer type.
90     STAFRefPtr &operator=(const TheType *);
91 
92     TheType *fPtr;
93     Type fType;
94     union
95     {
96         TypeFreeFunction fFreeFunc;
97         TypeArrayFreeFunction fArrayFreeFunc;
98     };
99     unsigned int fSize;
100     STAFThreadSafeScalar_t *fCount;
101 };
102 
103 template <class TheType>
STAFRefPtr()104 inline STAFRefPtr<TheType>::STAFRefPtr() : fPtr(0), fType(SCALAR), fFreeFunc(0),
105                                            fCount(0), fSize(0)
106 { /* Do Nothing */ }
107 
108 template <class TheType>
STAFRefPtr(TheType * ptr,Init init,Type type,TypeFreeFunction freeFunc)109 inline STAFRefPtr<TheType>::STAFRefPtr(TheType *ptr, Init init, Type type,
110                                        TypeFreeFunction freeFunc)
111     : fPtr(ptr), fType(type), fFreeFunc(freeFunc), fCount(0), fSize(0)
112 {
113     fCount = new STAFThreadSafeScalar_t(1);
114 }
115 
116 template <class TheType>
STAFRefPtr(TheType * ptr,Init init,unsigned int size,TypeArrayFreeFunction freeFunc)117 inline STAFRefPtr<TheType>::STAFRefPtr(TheType *ptr, Init init,
118                                        unsigned int size,
119                                        TypeArrayFreeFunction freeFunc)
120     : fPtr(ptr), fType(CUSTOMARRAY), fArrayFreeFunc(freeFunc), fCount(0),
121       fSize(size)
122 {
123     fCount = new STAFThreadSafeScalar_t(1);
124 }
125 
126 template <class TheType>
STAFRefPtr(const STAFRefPtr & from)127 inline STAFRefPtr<TheType>::STAFRefPtr(const STAFRefPtr &from)
128     : fPtr(from.fPtr), fType(from.fType), fSize(from.fSize), fCount(from.fCount)
129 {
130     if (fType == CUSTOMARRAY)
131         fArrayFreeFunc = from.fArrayFreeFunc;
132     else
133         fFreeFunc = from.fFreeFunc;
134 
135     if (fCount != 0)
136         STAFThreadSafeIncrement(fCount);
137 }
138 
139 template <class TheType>
140 inline STAFRefPtr<TheType> &STAFRefPtr<TheType>::operator=(const STAFRefPtr &from)
141 {
142     if (fPtr == from.fPtr) return *this;
143 
144     if (fCount != 0)
145     {
146         if (STAFThreadSafeDecrement(fCount) == 0)
147         {
148             if (fType == SCALAR) delete fPtr;
149             else if (fType == ARRAY) delete [] fPtr;
150             else if (fType == CUSTOM) fFreeFunc(fPtr);
151             else fArrayFreeFunc(fPtr, fSize);
152 
153             delete fCount;
154         }
155     }
156 
157     fPtr = from.fPtr;
158     fType = from.fType;
159     fFreeFunc = from.fFreeFunc;
160     fSize = from.fSize;
161     fCount = from.fCount;
162 
163     if (fCount != 0)
164         STAFThreadSafeIncrement(fCount);
165 
166     return *this;
167 }
168 
169 template <class TheType>
170 inline bool STAFRefPtr<TheType>::operator==(const STAFRefPtr &rhs)
171 {
172     return (fPtr == rhs.fPtr);
173 }
174 
175 template <class TheType>
~STAFRefPtr()176 inline STAFRefPtr<TheType>::~STAFRefPtr()
177 {
178     if (fCount != 0)
179     {
180         if (STAFThreadSafeDecrement(fCount) == 0)
181         {
182             if (fType == SCALAR) delete fPtr;
183             else if (fType == ARRAY) delete [] fPtr;
184             else if (fType == CUSTOM) fFreeFunc(fPtr);
185             else fArrayFreeFunc(fPtr, fSize);
186 
187             delete fCount;
188         }
189     }
190 }
191 
192 // End #ifdef __cplusplus
193 
194 #endif
195 
196 #endif
197