|
mmapio.h00001 #ifndef __CS_MEMORY_MAPPED_IO__ 00002 #define __CS_MEMORY_MAPPED_IO__ 00003 00004 #ifndef CS_HAS_MEMORY_MAPPED_IO 00005 #include "csutil/bitarray.h" 00006 #endif 00007 00008 /******************************************************************* 00009 00010 Design notes: 00011 00012 1. Although the offset and page in the cache block can both be 00013 calculated from either value, i chose to precalculate and store 00014 BOTH items. The reason for this is that it avoids one 00015 multiplication on each access, and one division when paging data 00016 in to cache. For the default values data storage per cache is 00017 8192 bytes with 20 bytes additional overhead. This means that 00018 0.2% of the data is overhead. That's worth it to avoid a heavy 00019 op like multiplication 00020 00021 2. Usage of the singly-linked list for storage was chosen over a 00022 static array of cache blocks because there's no simple way to 00023 provide a direct index into the cache list from the index or page. 00024 Since we can probably guarantee that all blocks are NOT going to 00025 be in memory at once, we cannot index into the array based on a 00026 page index, etc. A sorted list would probably provide the fastest 00027 lookup times, but would it be worth the overhead? A hash table 00028 provides a number of short lists, which in this case are unsorted. 00029 Using QuickSort, lookup on a sorted table of 2048 entries would take 00030 about log2(2048) operations. With the default hash table size, each 00031 list is about 1.5 entries long if spread uniformly. This means that 00032 most lookups on a cache of this size should take between two and 00033 four operations per (counting the modulus.) While the hash table 00034 does consume about 4k more memory, I think the slight memory usage 00035 is worth it, considering the massive speedup. 00036 00037 *******************************************************************/ 00038 00039 00041 const unsigned csmmioDefaultCacheBlockSize = 256; 00042 00044 const unsigned csmmioDefaultCacheSize = 256;//2048; 00045 00047 const unsigned csmmioDefaultHashSize = 211;//1559; 00048 00049 00051 class csMemoryMappedIO 00052 { 00054 unsigned int block_size; 00055 00057 bool valid_mmio_object; 00058 00059 #ifndef CS_HAS_MEMORY_MAPPED_IO 00060 00062 unsigned cache_block_size; 00063 00065 unsigned int cache_max_size; 00066 00068 unsigned int cache_block_count; 00069 00071 csBitArray *page_map; 00072 00073 #ifdef CS_DEBUG 00074 00075 public: 00077 unsigned int hits; 00078 00080 unsigned int misses; 00081 00082 private: 00083 #endif 00084 00086 struct CacheBlock 00087 { 00089 unsigned age; 00090 00092 unsigned offset; 00093 00095 unsigned page; 00096 00098 CacheBlock *next; 00099 00101 unsigned char *data; 00102 }; 00103 00105 CacheBlock *cache[csmmioDefaultHashSize]; 00106 00107 // Software specific mmioInfo struct, should only be defined for platforms w/o hardware mmio. 00108 struct mmioInfo 00109 { 00111 FILE *hMappedFile; 00112 00114 unsigned char *data; 00115 00117 unsigned int file_size; 00118 } platform; 00119 00120 #else 00121 00123 mmioInfo platform; 00124 00125 #endif // end else doesn't have memory-mapped i/o 00126 00127 public: 00130 csMemoryMappedIO(unsigned _block_size, char *filename); 00131 00134 csMemoryMappedIO::~csMemoryMappedIO(); 00135 00139 inline void *GetPointer(unsigned int index) 00140 { 00141 #ifdef CS_HAS_MEMORY_MAPPED_IO 00142 00143 return platform.data + (index*block_size); 00144 00145 #else 00146 00147 unsigned int page = index/cache_block_size; 00148 00149 if (!valid_mmio_object) return NULL; 00150 00151 if (!(*page_map)[page]) 00152 { 00153 #ifdef CS_DEBUG 00154 ++misses; 00155 #endif 00156 CachePage(page); 00157 } 00158 #ifdef CS_DEBUG 00159 else ++hits; 00160 #endif 00161 00162 // This MUST come AFTER CachPage b/c CachePage might re-orient things. 00163 CacheBlock *cp = cache[page % csmmioDefaultHashSize]; 00164 00165 while(cp) 00166 { 00167 if (cp->page==page) 00168 { 00169 // Decrease age 00170 ++cp->age; 00171 00172 return cp->data + ((index-cp->offset)*block_size); 00173 } 00174 00175 cp=cp->next; 00176 } 00177 00178 //Serious error! The page is marked as here, but we could not find it! 00179 return NULL; 00180 00181 #endif 00182 00183 } 00184 00185 #ifndef CS_HAS_MEMORY_MAPPED_IO 00186 00187 private: 00189 void CachePage(unsigned int page); 00190 00192 bool MemoryMapFile(mmioInfo *platform, char *filename); 00193 00195 void UnMemoryMapFile(mmioInfo *platform); 00196 00197 #endif 00198 00199 }; 00200 00201 #endif 00202 Generated for Crystal Space by doxygen 1.2.5 written by Dimitri van Heesch, ©1997-2000 |