Google

Main Page   Class Hierarchy   Compound List   File List   Compound Members  

mmapio.h

00001 #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