00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00036 #ifndef __ClassRef_h
00037 #define __ClassRef_h
00038
00039 #define __math_h_NO_ARRAYS
00040 #include "_math.h"
00041 #undef __math_h_NO_ARRAYS
00042 #include "errmsg.h"
00043
00044 typedef size_t size_type;
00045
00046
00047 template <class V>
00048 class ClassRef {
00049
00050 public:
00051
00053 static int num_refs_limit;
00054
00056 ClassRef() {own=DataNotOwned; ref=0; ref_ptrs=0; ptrlen=0; const_ref=FALSE;}
00058 virtual ~ClassRef() {if (ref_ptrs) delete [] ref_ptrs;}
00059
00061 void update_refs()
00062 {
00063 if (const_ref == TRUE)
00064 ErrAbort("Setting data for an ClassRef object with constant data references.");
00065 for (int i=0; i<ref; i++)
00066 copy_data(ref_ptrs[i]);
00067 }
00069 void acquire(V* array);
00071 bool release(V* array);
00073 void resize_ref_ptrs(const int);
00075 virtual void copy_data(V* array) = 0;
00077 virtual void reset_data(V* array) = 0;
00079 virtual void delete_data() = 0;
00080
00082 EnumDataOwned own;
00084 int ref;
00085
00087 void freeze()
00088 { const_ref=TRUE; }
00090 int const_ref;
00091
00092 protected:
00093
00095 int ptrlen;
00097 V** ref_ptrs;
00098 };
00099
00100
00101 template <class V>
00102 int ClassRef<V>::num_refs_limit=32;
00103
00104
00105
00106 template <class V>
00107 void ClassRef<V>::acquire(V* array)
00108 {
00109 if (const_ref == FALSE) {
00110
00111
00112
00113 if (ref == num_refs_limit)
00114 ErrAbort(errmsg("Exceeded maximum number of reference counts allowed in ClassRef<V>::num_refs_limit = %d",num_refs_limit));
00115
00116 if (ref == ptrlen)
00117 resize_ref_ptrs(ptrlen*2+2);
00118 ref_ptrs[ref++] = array;
00119 }
00120 copy_data(array);
00121 }
00122
00123
00124
00125 template <class V>
00126 bool ClassRef<V>::release(V* array)
00127 {
00128 if (const_ref == FALSE) {
00129 V** tmp = ref_ptrs;
00130 int i=0;
00131 for (i=0; i<(ref-1); i++, tmp++)
00132 if (*tmp == array) break;
00133 if (i < (ref-1))
00134 ref_ptrs[i] = ref_ptrs[--ref];
00135 else
00136 ref--;
00137 if ((ptrlen > 2) && (ref < ptrlen/2))
00138 resize_ref_ptrs(ref);
00139 }
00140 else
00141 ref--;
00142
00143 if (ref == 0) {
00144 delete_data();
00145 own = DataNotOwned;
00146 const_ref=FALSE;
00147 delete [] ref_ptrs;
00148 ref_ptrs = 0;
00149 }
00150
00151 reset_data(array);
00152 return (ref == 0);
00153 }
00154
00155
00156
00157 template <class V>
00158 void ClassRef<V>::resize_ref_ptrs(const int newlen)
00159 {
00160 V** tmp = new V* [newlen];
00161 if (ref) {
00162 for (int i=0; i<min(ref,newlen); i++)
00163 tmp[i] = ref_ptrs[i];
00164 delete [] ref_ptrs;
00165 }
00166 ptrlen = newlen;
00167 ref_ptrs=tmp;
00168 }
00169
00170
00171
00172 template <class T, class V>
00173 class ArrayRef : public ClassRef<V> {
00174
00175 public:
00176
00178 ArrayRef() {Len=0; Data=0;}
00180 virtual ~ArrayRef() {if (own) delete [] Data;}
00181
00183 void copy_data(V* array);
00185 void reset_data(V* array);
00187 void delete_data()
00188 { if (own) delete [] Data; Data=0; }
00189
00191 void set_data(T* Data_, size_type Len_, EnumDataOwned own_);
00192
00194 T* Data;
00196 size_type Len;
00197
00198 };
00199
00200
00201 template <class T, class V>
00202 void ArrayRef<T,V>::copy_data(V* array)
00203 {
00204 array->Data = Data;
00205 array->Len = Len;
00206 }
00207
00208
00209 template <class T, class V>
00210 void ArrayRef<T,V>::reset_data(V* array)
00211 {
00212 array->Data = 0;
00213 array->Len = 0;
00214 }
00215
00216
00217 template <class T, class V>
00218 void ArrayRef<T,V>::set_data(T* Data_, size_type Len_, EnumDataOwned own_)
00219 {
00220 if (const_ref == TRUE)
00221 ErrAbort("Setting data for an ArrayRef object with constant data references.");
00222
00223 if (Data && own && (Len > 0))
00224 delete [] Data;
00225 if (Len_ > 0) {
00226 Data = Data_;
00227 own = own_;
00228 Len = Len_;
00229 }
00230 else {
00231 Data=0;
00232 Len=0;
00233 own=DataNotOwned;
00234 }
00235 update_refs();
00236 }
00237
00238 #endif