00001
00003
00004
00005
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 #include "camtypes.h"
00105
00106 #include <iostream>
00107
00108 #include "gcache.h"
00109
00112
00113 CamCache::CamCache( size_t Size, UINT32 Log2MaxEntries )
00114 {
00115 HashTableSize = 1<<Log2MaxEntries ;
00116 HashTableMask = HashTableSize-1 ;
00117 HashTable = NULL ;
00118 CacheStart = NULL ;
00119
00120 HashTable = new ( CacheBlock* [HashTableSize] ) ;
00121 CacheStart = (CacheBlock*) new BYTE[Size+2*FreeCacheBlockSize] ;
00122
00123 if (!HashTable || !CacheStart)
00124 {
00125 if (HashTable)
00126 {
00127 delete [] HashTable ; HashTable = NULL ;
00128 }
00129 if (CacheStart)
00130 {
00131 delete [] CacheStart ; CacheStart = NULL ;
00132 }
00133 return ;
00134 }
00135 for ( size_t i=0 ; i<HashTableSize ; i++ )
00136 HashTable[i] = NULL ;
00137 CacheBlock *FreeBlock ;
00138 FreeBlock = (CacheBlock*) ((BYTE*)CacheStart+FreeCacheBlockSize) ;
00139 CacheEnd = (CacheBlock*) ((BYTE*)CacheStart+Size-FreeCacheBlockSize) ;
00140 CacheStart->Prev = CacheStart ;
00141 CacheEnd->Next = CacheEnd ;
00142 CacheStart->Next = CacheEnd->Prev =
00143 CacheStart->NextFree = CacheEnd->PrevFree = FreeBlock ;
00144 CacheStart->PrevFree = CacheEnd->NextFree = NULL ;
00145 CacheStart->State = CacheEnd->State = 0 ;
00146 FreeBlock->Prev = FreeBlock->PrevFree = CacheStart ;
00147 FreeBlock->Next = FreeBlock->NextFree = CacheEnd ;
00148 FreeBlock->State = FREE ;
00149 LeastUsed = MostUsed = NULL ;
00150 }
00151
00153
00154
00155
00156 BOOL CamCache::Verify()
00157 {
00158 return HashTable && CacheStart ;
00159 }
00160
00162
00163 CamCache::~CamCache()
00164 {
00165 delete [] HashTable ; HashTable = NULL ;
00166 delete [] CacheStart ; CacheStart = NULL ;
00167 }
00168
00171
00172 BOOL CamCache::FindPath( UINT32 Handle, INT32* &Points, BYTE* &Types, UINT32 &Length )
00173 {
00174 INT32 *Object = (INT32*) FindEntry( Handle ) ;
00175 if ( Object )
00176 {
00177 Length = *Object ;
00178 Points = ++Object ;
00179 Types = (BYTE*) (Object+2*Length) ;
00180 }
00181 return Object!=NULL ;
00182 }
00183
00184 void CamCache::AddPath( UINT32 Handle, INT32* Points, BYTE* Types, UINT32 Length )
00185 {
00186 INT32 *DPtr = (INT32*) AddEntry( Handle,Length*9+4 ) ;
00187 *DPtr++ = Length ;
00188 INT32 *SPtr = Points ;
00189 size_t i;
00190 for ( i=0 ; i<2*Length ; i++ )
00191 *DPtr++ = *SPtr++ ;
00192 SPtr = (INT32*) Types ;
00193 Length = (Length+3)>>2 ;
00194 for ( i=0 ; i<Length ; i++ )
00195 *DPtr++ = *SPtr++ ;
00196 }
00197
00200
00201 PORTNOTE("other","not used - removed because AddString looks dodgy")
00202 #ifndef EXCLUDE_FROM_XARALX
00203
00204 char* CamCache::FindString( UINT32 Handle )
00205 {
00206 return (char*) FindEntry( Handle ) ;
00207 }
00208
00209 void CamCache::AddString( UINT32 Handle, char* String )
00210 {
00211 size_t StringLength = cc_strlenBytes(String)+1 ;
00212 INT32 *SPtr = (INT32*) String ;
00213 INT32 *DPtr = (INT32*) AddEntry( Handle,StringLength ) ;
00214 StringLength = (StringLength+3)>>2 ;
00215 for ( size_t i=0 ; i<StringLength ; i++ )
00216 *DPtr++ = *SPtr++ ;
00217 }
00218 #endif
00219
00222
00223
00224 UINT32 Hash(UINT32 val)
00225 {
00226 val ^= (val << 7) | (val >> 25);
00227 val ^= (val << 11) | (val >> 21);
00228 val ^= (val << 19) | (val >> 13);
00229 val ^= (val << 16) | (val >> 16);
00230 return val;
00231 }
00232
00233 void* CamCache::FindEntry( UINT32 Handle )
00234 {
00235 UINT32 HashIndex = Hash( Handle ) & HashTableMask ;
00236 CacheBlock *Ptr = HashTable[HashIndex] ;
00237 while ( Ptr )
00238 if ( Ptr->Handle == Handle )
00239 {
00240 if ( Ptr != MostUsed )
00241 {
00242
00243 if ( Ptr==LeastUsed )
00244 LeastUsed = Ptr->NextUsed ;
00245 else
00246 Ptr->PrevUsed->NextUsed = Ptr->NextUsed ;
00247 Ptr->NextUsed->PrevUsed = Ptr->PrevUsed ;
00248 Ptr->NextUsed = NULL ;
00249 Ptr->PrevUsed = MostUsed ;
00250 MostUsed->NextUsed = Ptr ;
00251 MostUsed = Ptr ;
00252 }
00253 return Ptr->Object ;
00254 }
00255 else
00256 Ptr = Ptr->Link ;
00257
00258 return NULL ;
00259 }
00260
00262
00263 void* CamCache::AddEntry( UINT32 Handle, size_t ObjectSize )
00264 {
00265 UINT32 HashIndex = Hash( Handle ) & HashTableMask ;
00266 CacheBlock *Ptr = HashTable[HashIndex] ;
00267 while ( Ptr )
00268 if ( Ptr->Handle == Handle )
00269 return Ptr->Object ;
00270 else
00271 Ptr = Ptr->Link ;
00272 CacheBlock *FreeBlock = CacheStart->NextFree ;
00273 size_t ObjectBlockSize = (ObjectSize+UsedCacheBlockSize+3) & ~3 ;
00274 while ( ObjectBlockSize > BlockSize(FreeBlock) )
00275 if ( !(FreeBlock=FreeBlock->NextFree) )
00276 {
00277
00278 UINT32 HashIndex = Hash( LeastUsed->Handle ) & HashTableMask ;
00279 CacheBlock *Ptr = HashTable[HashIndex] ;
00280 if ( Ptr == LeastUsed )
00281 HashTable[HashIndex] = LeastUsed->Link ;
00282 else
00283 {
00284 while ( Ptr->Link != LeastUsed )
00285 Ptr = Ptr->Link ;
00286 Ptr->Link = LeastUsed->Link ;
00287 }
00288
00289 FreeBlock = LeastUsed ;
00290 LeastUsed = LeastUsed->NextUsed ;
00291 LeastUsed->PrevUsed = NULL ;
00292 FreeBlock->State = FREE ;
00293 CacheStart->NextFree->PrevFree = FreeBlock ;
00294 FreeBlock->NextFree = CacheStart->NextFree ;
00295 FreeBlock->PrevFree = CacheStart ;
00296 CacheStart->NextFree = FreeBlock ;
00297 CacheBlock *NextBlock = FreeBlock->Next ;
00298 CacheBlock *PrevBlock = FreeBlock->Prev ;
00299 if ( NextBlock->State == FREE )
00300 {
00301 NextBlock->PrevFree->NextFree = NextBlock->NextFree ;
00302 NextBlock->NextFree->PrevFree = NextBlock->PrevFree ;
00303 FreeBlock->Next = NextBlock->Next ;
00304 NextBlock->Next->Prev = FreeBlock ;
00305 }
00306 if ( PrevBlock->State == FREE )
00307 {
00308 FreeBlock->PrevFree->NextFree = FreeBlock->NextFree ;
00309 FreeBlock->NextFree->PrevFree = FreeBlock->PrevFree ;
00310 PrevBlock->Next = FreeBlock->Next ;
00311 FreeBlock->Next->Prev = PrevBlock ;
00312 FreeBlock = PrevBlock ;
00313 }
00314 }
00315
00316 if ( ObjectBlockSize+FreeCacheBlockSize > BlockSize(FreeBlock) )
00317 {
00318 FreeBlock->PrevFree->NextFree = FreeBlock->NextFree ;
00319 FreeBlock->NextFree->PrevFree = FreeBlock->PrevFree ;
00320 }
00321 else
00322 {
00323 CacheBlock *NewBlock = (CacheBlock*) ((BYTE*)FreeBlock+ObjectBlockSize) ;
00324 NewBlock->Prev = FreeBlock ;
00325 NewBlock->Next = FreeBlock->Next ;
00326 NewBlock->State = FREE ;
00327 NewBlock->NextFree = FreeBlock->NextFree ;
00328 NewBlock->PrevFree = FreeBlock->PrevFree ;
00329 NewBlock->NextFree->PrevFree = NewBlock->PrevFree->NextFree = NewBlock ;
00330 FreeBlock->Next = NewBlock->Next->Prev = NewBlock ;
00331 }
00332 FreeBlock->Link = HashTable[HashIndex] ;
00333 FreeBlock->PrevUsed = MostUsed ;
00334 FreeBlock->NextUsed = NULL ;
00335 FreeBlock->Handle = Handle ;
00336 HashTable[HashIndex] = FreeBlock ;
00337 if ( MostUsed )
00338 MostUsed->NextUsed = FreeBlock ;
00339 MostUsed = FreeBlock ;
00340 if ( !LeastUsed )
00341 LeastUsed = FreeBlock ;
00342 return FreeBlock->Object ;
00343 }
00344
00347
00348 #ifdef _DEBUG
00349
00350 ostream& operator << ( ostream& os, CamCache& Cache )
00351 {
00352 for ( size_t i=0 ; i<Cache.HashTableSize ; i++ )
00353 {
00354 os << Cache.HashTable[i] << " " ;
00355 if ( (i & 7) == 7 )
00356 os << endl ;
00357 }
00358 os << "Start : " << Cache.CacheStart
00359 << ", " << Cache.CacheStart->Prev << "," << Cache.CacheStart->Next
00360 << ", " << Cache.CacheStart->PrevFree << "," << Cache.CacheStart->NextFree << endl ;
00361 CacheBlock *Ptr = Cache.CacheStart->Next ;
00362 while ( Ptr != Cache.CacheEnd )
00363 {
00364 if ( Ptr->State == FREE )
00365 cout << "FREE : " << Ptr << ", " << Ptr->Prev << "," << Ptr->Next
00366 << ", " << Ptr->PrevFree << "," << Ptr->NextFree
00367 << " (" << hex
00368 << Cache.BlockSize(Ptr)-FreeCacheBlockSize
00369 << dec << ")" << endl ;
00370 else
00371 cout << "USED : " << Ptr << ", " << Ptr->Prev << "," << Ptr->Next
00372 << ", " << Ptr->PrevUsed << "," << Ptr->NextUsed
00373 << ", " << Ptr->Link << "," << Ptr->Handle
00374 << ", " << (char*) Ptr->Object << " (" << hex
00375 #ifndef EXCLUDE_FROM_XARALX
00376 << Cache.BlockSize(Ptr)-UsedCacheBlockSize-cc_strlenBytes((char*)Ptr->Object)-1
00377 #endif
00378 << dec << ")" << endl ;
00379 Ptr = Ptr->Next ;
00380 }
00381 os << "End : " << Cache.CacheEnd
00382 << ", " << Cache.CacheEnd->Prev << "," << Cache.CacheEnd->Next
00383 << ", " << Cache.CacheEnd->PrevFree << "," << Cache.CacheEnd->NextFree << endl ;
00384 os << "LeastUsed : " << Cache.LeastUsed << endl ;
00385 os << " MostUsed : " << Cache. MostUsed << endl ;
00386 return os ;
00387 }
00388
00389 #endif
00390