00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __loaded__data_reference_count_h__
00021 #define __loaded__data_reference_count_h__
00022 using namespace std;
00023 #line 1 "data-reference-count.h++"
00024 #include <cstdio>
00025 #include <set>
00026 #include <stdio.h>
00027 #include <typeinfo>
00028 #include "reference-count.h"
00029
00034 #ifdef DATA_RO_FIELD
00035 typedef enum {ReadOnly, Writeable} DataAccessFlag;
00036 #define W2R_CACHING
00037 #define CLONE_STATS
00038
00039 template<class T>
00040 class DataKeyCmp
00041 {
00042 public:
00043 bool operator()(T* a, T* b)
00044 {
00045 return a->smaller_than(b);
00046 };
00047 };
00048 #endif
00049
00050 class DataReferenceCount: public ReferenceCount
00051 {
00052 public:
00053 #ifdef DATA_RO_FIELD
00054 bool readonly;
00055 #endif
00056
00061 Smart<ReferenceCount> readonly_clone;
00062 DataReferenceCount()
00063 #ifdef DATA_RO_FIELD
00064 : readonly(false)
00065 #endif
00066 {
00067 }
00068
00073 virtual DataReferenceCount* clone() = 0;
00077 #ifdef DATA_RO_FIELD
00078 virtual void change_access(DataAccessFlag flag)
00079 {
00080 if (flag==ReadOnly)
00081 readonly=true;
00082 else if (flag==Writeable)
00083 readonly=false;
00084 else assert(0);
00085 }
00086 void will_write()
00087 {
00088 readonly_clone=Smart<ReferenceCount>();
00089 assert(!readonly);
00090 }
00091 #endif
00092
00095 DataReferenceCount& operator =(const DataReferenceCount& r)
00096 {
00097 assert(0);
00098 }
00105 virtual DataReferenceCount* reallocate()
00106 {
00107 assert(0);
00108 };
00109 };
00110
00111 #ifdef DATA_RO_FIELD
00112 #ifdef CLONE_STATS
00113 extern long fast_comparisons;
00114 extern long slow_comparisons;
00115 extern long r2w_cloned;
00116 extern long w2r_cached;
00117 extern long w2r_real_clone;
00118 extern long w2r_known_clone;
00119 extern long w2r_known_singleref;
00120 extern long w2r_unknown_singleref;
00121 #endif
00122 #endif
00123
00130 template <class ReferenceCountedObject>
00131 class DataSmart: public Smart<ReferenceCountedObject>
00132 {
00133 public:
00134 explicit DataSmart(ReferenceCountedObject* p = 0) : Smart<ReferenceCountedObject>(p)
00135 {
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 #ifdef DATA_RO_FIELD
00165 void change_access(DataAccessFlag flag)
00166 {
00167 if (flag==ReadOnly) make_readonly();
00168 else if(flag==Writeable) make_writeable();
00169 else assert(0);
00170 }
00171 #endif
00172
00173 bool operator<(const DataSmart<ReferenceCountedObject> & other) const
00174 {
00175 if (this->ptr==NULL) return other.ptr;
00176 if (other.ptr==NULL) return false;
00177 #ifdef DATA_RO_FIELD
00178 if (this->ptr->readonly && other.ptr->readonly)
00179 {
00180 fast_comparisons++;
00181 return this->ptr<other.ptr;
00182 }
00183 slow_comparisons++;
00184 #endif
00185 if (this->ptr==other.ptr) return false;
00186 if (typeid(*(this->ptr))==typeid(*other.ptr))
00187 return this->ptr->most_specialized_smaller_than(other.ptr);
00188 return typeid(*(this->ptr)).before(typeid(*(other.ptr)));
00189 }
00190
00191 #ifdef DATA_RO_FIELD
00192
00195 void make_readonly()
00196 {
00197 if (this->ptr==NULL) return;
00198 if (this->ptr->readonly) return;
00203 #ifdef W2R_CACHING
00204 if (this->ptr->readonly_clone.ptr!=NULL)
00205 {
00206 #ifdef CLONE_STATS
00207 w2r_cached++;
00208 #endif
00209 DataReferenceCount* cloned = (DataReferenceCount*)Smart<ReferenceCountedObject>::ptr->readonly_clone.ptr;
00210 cloned->incref();
00211 Smart<ReferenceCountedObject>::decref();
00212 Smart<ReferenceCountedObject>::ptr=(ReferenceCountedObject*)cloned;
00213 }
00214 else
00215 #endif
00216
00219 if (this->ptr->reference_count==1)
00220 {
00221 this->ptr->change_access(ReadOnly);
00222 assert(this->ptr->readonly);
00223 DataReferenceCount* unique = this->ptr->reallocate();
00224 if (unique==this->ptr)
00225 {
00226 #ifdef CLONE_STATS
00227 w2r_unknown_singleref++;
00228 #endif
00229 }
00230 else
00231 {
00232 #ifdef CLONE_STATS
00233 w2r_known_singleref++;
00234 #endif
00235 assert(unique->readonly);
00236 unique->incref();
00237 Smart<ReferenceCountedObject>::decref();
00238 this->ptr=(ReferenceCountedObject*)unique;
00239 }
00240 }
00241 else
00242 {
00243 DataReferenceCount* unique;
00244 {
00245 DataReferenceCount* cloned = Smart<ReferenceCountedObject>::ptr->clone();
00246 cloned->readonly=false;
00247 cloned->change_access(ReadOnly);
00248 assert(cloned->readonly);
00249 unique = cloned->reallocate();
00250 if (unique==cloned)
00251 {
00252 #ifdef CLONE_STATS
00253 w2r_real_clone++;
00254 #endif
00255 }
00256 else
00257 {
00258 delete(cloned);
00259 #ifdef CLONE_STATS
00260 w2r_known_clone++;
00261 #endif
00262 }
00263 }
00264 assert(unique->readonly);
00265 unique->incref();
00266 this->ptr->readonly_clone=Smart<ReferenceCount>(unique);
00267 Smart<ReferenceCountedObject>::decref();
00268 Smart<ReferenceCountedObject>::ptr=(ReferenceCountedObject*)unique;
00269 assert(Smart<ReferenceCountedObject>::ptr->readonly);
00270 }
00271 }
00272 void make_writeable()
00273 {
00274 if (!Smart<ReferenceCountedObject>::ptr) return;
00275 if (!Smart<ReferenceCountedObject>::ptr->readonly) return;
00276 #ifdef CLONE_STATS
00277 r2w_cloned++;
00278 #endif
00279 DataReferenceCount* cloned = Smart<ReferenceCountedObject>::ptr->clone();
00280 cloned->readonly_clone=Smart<ReferenceCount>(this->ptr);
00281 cloned->readonly=false;
00282 cloned->incref();
00283 Smart<ReferenceCountedObject>::decref();
00284 Smart<ReferenceCountedObject>::ptr=(ReferenceCountedObject*)cloned;
00285 Smart<ReferenceCountedObject>::ptr->change_access(Writeable);
00286 assert(!Smart<ReferenceCountedObject>::ptr->readonly);
00287 }
00288 #endif
00289 };
00290
00291
00292 #ifdef DATA_RO_FIELD
00293
00294 extern unsigned long long readonly_allocated;
00295 extern unsigned long long readonly_not_allocated;
00296 template<class T>
00297 class Uniqueifier
00298 {
00299 set<T*,DataKeyCmp<T> > c;
00300 public:
00301 T* reallocate(T* a)
00302 {
00303 assert(a->readonly);
00304 a->readonly=false;
00305 if (c.find(a)==c.end())
00306 {
00307 #ifdef CLONE_STATS
00308 readonly_allocated+=sizeof(T);
00309 #endif
00310 a->incref();
00311 c.insert(a);
00312 a->readonly=true;
00313 return a;
00314 }
00315 #ifdef CLONE_STATS
00316 readonly_not_allocated+=sizeof(T);
00317 #endif
00318 T* r = *(c.find(a));
00319 assert(r!=a);
00320 #ifdef PRINT_MAPPINGS
00321 printf("Mapping ");
00322 a->print(1);
00323 printf(" ==> ");
00324 r->print(1);
00325 printf("\n");
00326 if ((r->smaller_than(a) || a->smaller_than(r))
00327 || r->smaller_than(r))
00328 {
00329 printf("ERROR\n");
00330 fflush(stdout);
00331 exit(0);
00332 }
00333 #endif
00334 a->readonly=true;
00335 return r;
00336 }
00337 };
00338 #endif
00339 #endif // __loaded__data_reference_count_h__