Blender V2.61 - r43446
|
00001 /* 00002 * Cache.hpp 00003 * 00004 * Created on: Feb 24, 2009 00005 * Author: benoit tbolsee 00006 */ 00007 00008 #ifndef CACHE_HPP_ 00009 #define CACHE_HPP_ 00010 00011 #include <map> 00012 00013 namespace iTaSC { 00014 00015 #define CACHE_LOOKUP_TABLE_SIZE 128 00016 #define CACHE_DEFAULT_BUFFER_SIZE 32768 00017 #define CACHE_CHANNEL_EXTEND_SIZE 10 00018 #define CACHE_MAX_ITEM_SIZE 0x3FFF0 00019 00020 /* macro to get the alignement gap after an item header */ 00021 #define CACHE_ITEM_GAPB(item) (unsigned int)(((size_t)item+sizeof(CacheItem))&(sizeof(void*)-1)) 00022 /* macro to get item data position, item=CacheItem pointer */ 00023 #define CACHE_ITEM_DATA_POINTER(item) (void*)((unsigned char*)item+sizeof(CacheItem)+CACHE_ITEM_GAPB(item)) 00024 /* macro to get item size in 32bit words from item address and length, item=CacheItem pointer */ 00025 #define CACHE_ITEM_SIZEW(item,length) (unsigned int)((sizeof(CacheItem)+CACHE_ITEM_GAPB(item)+(((length)+3)&~0x3))>>2) 00026 /* macto to move from one item to the next, item=CacheItem pointer, updated by the macro */ 00027 #define CACHE_NEXT_ITEM(item) ((item)+(item)->m_sizeW) 00028 #define CACHE_BLOCK_ITEM_ADDR(chan,buf,block) (&(buf)->m_firstItem+(((unsigned int)(block)<<chan->m_positionToBlockShiftW)+(buf)->lookup[block].m_offsetW)) 00029 #define CACHE_ITEM_ADDR(buf,pos) (&(buf)->m_firstItem+(pos)) 00030 #define CACHE_ITEM_POSITIONW(buf,item) (unsigned int)(item-&buf->m_firstItem) 00031 00032 typedef unsigned int CacheTS; 00033 00034 struct Timestamp 00035 { 00036 double realTimestamp; 00037 double realTimestep; 00038 CacheTS cacheTimestamp; 00039 unsigned int numstep:8; 00040 unsigned int substep:1; 00041 unsigned int reiterate:1; 00042 unsigned int cache:1; 00043 unsigned int update:1; 00044 unsigned int interpolate:1; 00045 unsigned int dummy:19; 00046 00047 Timestamp() { memset(this, 0, sizeof(Timestamp)); } 00048 }; 00049 00050 /* utility function to return second timestamp to millisecond */ 00051 inline void setCacheTimestamp(Timestamp& timestamp) 00052 { 00053 if (timestamp.realTimestamp < 0.0 || timestamp.realTimestamp > 4294967.295) 00054 timestamp.cacheTimestamp = 0; 00055 else 00056 timestamp.cacheTimestamp = (CacheTS)(timestamp.realTimestamp*1000.0+0.5); 00057 } 00058 00059 00060 /* 00061 class Cache: 00062 Top level class, only one instance of this class should exists. 00063 A device (=constraint, object) uses this class to create a cache entry for its data. 00064 A cache entry is divided into cache channels, each providing a separate buffer for cache items. 00065 The cache channels must be declared by the devices before they can be used. 00066 The device must specify the largest cache item (limited to 256Kb) so that the cache 00067 buffer can be organized optimally. 00068 Cache channels are identified by small number (starting from 0) allocated by the cache system. 00069 Cache items are inserted into cache channels ordered by timestamp. Writing is always done 00070 at the end of the cache buffer: writing an item automatically clears all items with 00071 higher timestamp. 00072 A cache item is an array of bytes provided by the device; the format of the cache item is left 00073 to the device. 00074 The device can retrieve a cache item associated with a certain timestamp. The cache system 00075 returns a pointer that points directly in the cache buffer to avoid unnecessary copy. 00076 The pointer is guaranteed to be pointer aligned so that direct mapping to C structure is possible 00077 (=32 bit aligned on 32 systems and 64 bit aligned on 64 bits system). 00078 00079 Timestamp = rounded time in millisecond. 00080 */ 00081 00082 struct CacheEntry; 00083 struct CacheBuffer; 00084 struct CacheItem; 00085 struct CacheChannel; 00086 00087 class Cache 00088 { 00089 private: 00090 /* map between device and cache entry. 00091 Dynamically updated when more devices create cache channels */ 00092 typedef std::map<const void *, struct CacheEntry*> CacheMap; 00093 CacheMap m_cache; 00094 const CacheItem *getCurrentCacheItemInternal(const void *device, int channel, CacheTS timestamp); 00095 00096 public: 00097 Cache(); 00098 ~Cache(); 00099 /* add a cache channel, maxItemSize must be < 256k. 00100 name : channel name, truncated at 31 characters 00101 msxItemSize : maximum size of item in bytes, items of larger size will be rejected 00102 return value >= 0: channel id, -1: error */ 00103 int addChannel(const void *device, const char *name, unsigned int maxItemSize); 00104 00105 /* delete a cache channel (and all associated buffers and items) */ 00106 int deleteChannel(const void *device, int channel); 00107 /* delete all channels of a device and remove the device from the map */ 00108 int deleteDevice(const void *device); 00109 /* removes all cache items, leaving the special item at timestamp=0. 00110 if device=NULL, apply to all devices. */ 00111 void clearCacheFrom(const void *device, CacheTS timestamp); 00112 00113 /* add a new cache item 00114 channel: the cache channel (as returned by AddChannel 00115 data, length: the cache item and length in bytes 00116 If data is NULL, the memory is allocated in the cache but not writen 00117 return: error: NULL, success: pointer to item in cache */ 00118 void *addCacheItem(const void *device, int channel, CacheTS timestamp, void *data, unsigned int length); 00119 00120 /* specialized function to add a vector of double in the cache 00121 It will first check if a vector exist already in the cache for the same timestamp 00122 and compared the cached vector with the new values. 00123 If all values are within threshold, the vector is updated but the cache is not deleted 00124 for the future timestamps. */ 00125 double *addCacheVectorIfDifferent(const void *device, int channel, CacheTS timestamp, double *data, unsigned int length, double threshold); 00126 00127 /* returns the cache item with timestamp that is just before the given timestamp. 00128 returns the data pointer or NULL if there is no cache item before timestamp. 00129 On return, timestamp is updated with the actual timestamp of the item being returned. 00130 Note that the length of the item is not returned, it is up to the device to organize 00131 the data so that length can be retrieved from the data if needed. 00132 Device can NULL, it will then just look the first channel available, useful to 00133 test the status of the cache. */ 00134 const void *getPreviousCacheItem(const void *device, int channel, CacheTS *timestamp); 00135 00136 /* returns the cache item with the timestamp that is exactly equal to the given timestamp 00137 If there is no cache item for this timestamp, returns NULL.*/ 00138 const void *getCurrentCacheItem(const void *device, int channel, CacheTS timestamp); 00139 00140 }; 00141 00142 /* the following structures are not internal use only, they should not be used directly */ 00143 00144 struct CacheEntry 00145 { 00146 CacheChannel *m_channelArray; // array of channels, automatically resized if more channels are created 00147 unsigned int m_count; // number of channel in channelArray 00148 CacheEntry() : m_channelArray(NULL), m_count(0) {} 00149 ~CacheEntry(); 00150 }; 00151 00152 struct CacheChannel 00153 { 00154 CacheItem* initItem; // item corresponding to timestamp=0 00155 struct CacheBuffer *m_firstBuffer; // first buffer of list 00156 struct CacheBuffer *m_lastBuffer; // last buffer of list to which an item was written 00157 char m_name[32]; // channel name 00158 unsigned char m_busy; // =0 if channel is free, !=0 when channel is in use 00159 unsigned char m_positionToBlockShiftW; // number of bits to shift a position in word to get the block number 00160 unsigned short m_positionToOffsetMaskW; // bit mask to apply on a position in word to get offset in a block 00161 unsigned int m_maxItemSizeB; // maximum item size in bytes 00162 unsigned int m_bufferSizeW; // size of item buffer in word to allocate when a new buffer must be created 00163 unsigned int m_blockSizeW; // block size in words of the lookup table 00164 unsigned int m_lastTimestamp; // timestamp of the last item that was written 00165 unsigned int m_lastItemPositionW; // position in words in lastBuffer of the last item written 00166 void clear(); 00167 CacheBuffer* allocBuffer(); 00168 CacheItem* findItemOrLater(unsigned int timestamp, CacheBuffer **rBuffer); 00169 CacheItem* findItemEarlier(unsigned int timestamp, CacheBuffer **rBuffer); 00170 // Internal function: finds an item in a buffer that is < timeOffset 00171 // timeOffset must be a valid offset for the buffer and the buffer must not be empty 00172 // on return highBlock contains the block with items above or equal to timeOffset 00173 CacheItem *_findBlock(CacheBuffer *buffer, unsigned short timeOffset, unsigned int *highBlock); 00174 }; 00175 00176 struct CacheBlock { 00177 unsigned short m_timeOffset; // timestamp relative to m_firstTimestamp 00178 unsigned short m_offsetW; // position in words of item relative to start of block 00179 }; 00180 00181 /* CacheItem is the header of each item in the buffer, must be 32bit 00182 Items are always 32 bits aligned and size is the number of 32 bit words until the 00183 next item header, including an eventual pre and post padding gap for pointer alignment */ 00184 struct CacheItem 00185 { 00186 unsigned short m_timeOffset; // timestamp relative to m_firstTimestamp 00187 unsigned short m_sizeW; // size of item in 32 bit words 00188 // item data follows header immediately or after a gap if position is not pointer aligned 00189 }; 00190 00191 // Buffer header 00192 // Defined in a macro to avoid sizeof() potential problem. 00193 // next for linked list. = NULL for last buffer 00194 // m_firstTimestamp timestamp of first item in this buffer 00195 // m_lastTimestamp timestamp of last item in this buffer 00196 // m_lastTimestamp must be < m_firstTimestamp+65536 00197 // m_lastItemPositionW position in word of last item written 00198 // m_firstFreePositionW position in word where a new item can be written, 0 if buffer is empty 00199 // lookup lookup table for fast access to item by timestamp 00200 // The buffer is divided in blocks of 2**n bytes with n chosen so that 00201 // there are no more than CACHE_LOOKUP_TABLE_SIZE blocks and that each 00202 // block will contain at least one item. 00203 // Each element of the lookup table gives the timestamp and offset 00204 // of the last cache item occupying (=starting in) the corresponding block. 00205 #define CACHE_HEADER \ 00206 struct CacheBuffer *m_next; \ 00207 unsigned int m_firstTimestamp; \ 00208 unsigned int m_lastTimestamp; \ 00209 \ 00210 unsigned int m_lastItemPositionW; \ 00211 unsigned int m_firstFreePositionW;\ 00212 struct CacheBlock lookup[CACHE_LOOKUP_TABLE_SIZE] 00213 00214 struct CacheBufferHeader { 00215 CACHE_HEADER; 00216 }; 00217 #define CACHE_BUFFER_HEADER_SIZE (sizeof(struct CacheBufferHeader)) 00218 struct CacheBuffer 00219 { 00220 CACHE_HEADER; 00221 struct CacheItem m_firstItem; // the address of this field marks the start of the buffer 00222 }; 00223 00224 00225 } 00226 00227 #endif /* CACHE_HPP_ */