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__