Blender  V2.93
Cache.cpp
Go to the documentation of this file.
1 
4 /*
5  * Cache.cpp
6  *
7  * Created on: Feb 24, 2009
8  * Author: benoit bolsee
9  */
10 #include <string.h>
11 #include <assert.h>
12 #include <math.h>
13 #include <stdlib.h>
14 #include "Cache.hpp"
15 
16 namespace iTaSC {
17 
19 {
20  for (unsigned int id=0; id < m_count; id++)
21  m_channelArray[id].clear();
22  if (m_channelArray)
24 }
25 
26 CacheItem *CacheChannel::_findBlock(CacheBuffer *buffer, unsigned short timeOffset, unsigned int *retBlock)
27 {
28  // the timestamp is necessarily in this buffer
29  unsigned int lowBlock, highBlock, midBlock;
30  if (timeOffset <= buffer->lookup[0].m_timeOffset) {
31  // special case: the item is in the first block, search from start
32  *retBlock = 0;
33  return &buffer->m_firstItem;
34  }
35  // general case, the item is in the middle of the buffer
36  // before doing a dycotomic search, we will assume that timestamp
37  // are regularly spaced so that we can try to locate the block directly
38  highBlock = buffer->m_lastItemPositionW>>m_positionToBlockShiftW;
39  lowBlock = midBlock = (timeOffset*highBlock)/(buffer->m_lastTimestamp-buffer->m_firstTimestamp);
40  // give some space for security
41  if (lowBlock > 0)
42  lowBlock--;
43  if (timeOffset <= buffer->lookup[lowBlock].m_timeOffset) {
44  // bad guess, but we know this block is a good high block, just use it
45  highBlock = lowBlock;
46  lowBlock = 0;
47  } else {
48  // ok, good guess, now check the high block, give some space
49  if (midBlock < highBlock)
50  midBlock++;
51  if (timeOffset <= buffer->lookup[midBlock].m_timeOffset) {
52  // good guess, keep that block as the high block
53  highBlock = midBlock;
54  }
55  }
56  // the item is in a different block, do a dycotomic search
57  // the timestamp is alway > lowBlock and <= highBlock
58  while (1) {
59  midBlock = (lowBlock+highBlock)/2;
60  if (midBlock == lowBlock) {
61  // low block and high block are contigous, we can start search from the low block
62  break;
63  } else if (timeOffset <= buffer->lookup[midBlock].m_timeOffset) {
64  highBlock = midBlock;
65  } else {
66  lowBlock = midBlock;
67  }
68  }
69  assert (lowBlock != highBlock);
70  *retBlock = highBlock;
71  return CACHE_BLOCK_ITEM_ADDR(this,buffer,lowBlock);
72 }
73 
75 {
77  for (buffer=m_firstBuffer; buffer != 0; buffer = next) {
78  next = buffer->m_next;
79  free(buffer);
80  }
83  if (initItem) {
84  free(initItem);
85  initItem = NULL;
86  }
87 }
88 
90 {
92  if (!m_busy)
93  return NULL;
95  if (buffer) {
96  memset(buffer, 0, CACHE_BUFFER_HEADER_SIZE);
97  }
98  return buffer;
99 }
100 
101 CacheItem* CacheChannel::findItemOrLater(unsigned int timestamp, CacheBuffer **rBuffer)
102 {
104  CacheItem *item, *limit;
105  if (!m_busy)
106  return NULL;
107  if (timestamp == 0 && initItem) {
108  *rBuffer = NULL;
109  return initItem;
110  }
111  for (buffer=m_firstBuffer; buffer; buffer = buffer->m_next) {
112  if (buffer->m_firstFreePositionW == 0)
113  // buffer is empty, this must be the last and we didn't find the timestamp
114  return NULL;
115  if (timestamp < buffer->m_firstTimestamp) {
116  *rBuffer = buffer;
117  return &buffer->m_firstItem;
118  }
119  if (timestamp <= buffer->m_lastTimestamp) {
120  // the timestamp is necessarily in this buffer
121  unsigned short timeOffset = (unsigned short)(timestamp-buffer->m_firstTimestamp);
122  unsigned int highBlock;
123  item = _findBlock(buffer, timeOffset, &highBlock);
124  // now we do a linear search until we find a timestamp that is equal or higher
125  // we should normally always find an item but let's put a limit just in case
126  limit = CACHE_BLOCK_ITEM_ADDR(this,buffer,highBlock);
127  while (item<=limit && item->m_timeOffset < timeOffset )
128  item = CACHE_NEXT_ITEM(item);
129  assert(item<=limit);
130  *rBuffer = buffer;
131  return item;
132  }
133  // search in next buffer
134  }
135  return NULL;
136 }
137 
138 CacheItem* CacheChannel::findItemEarlier(unsigned int timestamp, CacheBuffer **rBuffer)
139 {
140  CacheBuffer *buffer, *prevBuffer;
141  CacheItem *item, *limit, *prevItem;
142  if (!m_busy)
143  return NULL;
144  if (timestamp == 0)
145  return NULL;
146  for (prevBuffer=NULL, buffer=m_firstBuffer; buffer; prevBuffer = buffer, buffer = buffer->m_next) {
147  if (buffer->m_firstFreePositionW == 0)
148  // buffer is empty, this must be the last and we didn't find the timestamp
149  return NULL;
150  if (timestamp <= buffer->m_firstTimestamp) {
151  if (prevBuffer == NULL) {
152  // no item before, except the initial item
153  *rBuffer = NULL;
154  return initItem;
155  }
156  // the item is necessarily the last one of previous buffer
157  *rBuffer = prevBuffer;
158  return CACHE_ITEM_ADDR(prevBuffer,prevBuffer->m_lastItemPositionW);
159  }
160  if (timestamp <= buffer->m_lastTimestamp) {
161  // the timestamp is necessarily in this buffer
162  unsigned short timeOffset = (unsigned short)(timestamp-buffer->m_firstTimestamp);
163  unsigned int highBlock;
164  item = _findBlock(buffer, timeOffset, &highBlock);
165  // now we do a linear search until we find a timestamp that is equal or higher
166  // we should normally always find an item but let's put a limit just in case
167  limit = CACHE_BLOCK_ITEM_ADDR(this,buffer,highBlock);
168  prevItem = NULL;
169  while (item<=limit && item->m_timeOffset < timeOffset) {
170  prevItem = item;
171  item = CACHE_NEXT_ITEM(item);
172  }
173  assert(item<=limit && prevItem!=NULL);
174  *rBuffer = buffer;
175  return prevItem;
176  }
177  // search in next buffer
178  }
179  // pass all buffer, the last item is the last item of the last buffer
180  if (prevBuffer == NULL) {
181  // no item before, except the initial item
182  *rBuffer = NULL;
183  return initItem;
184  }
185  // the item is necessarily the last one of previous buffer
186  *rBuffer = prevBuffer;
187  return CACHE_ITEM_ADDR(prevBuffer,prevBuffer->m_lastItemPositionW);
188 }
189 
190 
192 {
193 }
194 
196 {
197  CacheMap::iterator it;
198  for (it=m_cache.begin(); it!=m_cache.end(); it=m_cache.begin()) {
199  deleteDevice(it->first);
200  }
201 }
202 
203 int Cache::addChannel(const void *device, const char *name, unsigned int maxItemSize)
204 {
205  CacheMap::iterator it = m_cache.find(device);
206  CacheEntry *entry;
207  CacheChannel *channel;
208  unsigned int id;
209 
210  if (maxItemSize > 0x3FFF0)
211  return -1;
212 
213  if (it == m_cache.end()) {
214  // device does not exist yet, create a new entry
215  entry = new CacheEntry();
216  if (entry == NULL)
217  return -1;
218  if (!m_cache.insert(CacheMap::value_type(device,entry)).second)
219  return -1;
220  } else {
221  entry = it->second;
222  }
223  // locate a channel with the same name and reuse
224  for (channel=entry->m_channelArray, id=0; id<entry->m_count; id++, channel++) {
225  if (channel->m_busy && !strcmp(name, channel->m_name)) {
226  // make this channel free again
227  deleteChannel(device, id);
228  // there can only be one channel with the same name
229  break;
230  }
231  }
232  for (channel=entry->m_channelArray, id=0; id<entry->m_count; id++, channel++) {
233  // locate a free channel
234  if (!channel->m_busy)
235  break;
236  }
237  if (id == entry->m_count) {
238  // no channel free, create new channels
239  int newcount = entry->m_count + CACHE_CHANNEL_EXTEND_SIZE;
240  channel = (CacheChannel*)realloc(entry->m_channelArray, newcount*sizeof(CacheChannel));
241  if (channel == NULL)
242  return -1;
243  entry->m_channelArray = channel;
244  memset(&entry->m_channelArray[entry->m_count], 0, CACHE_CHANNEL_EXTEND_SIZE*sizeof(CacheChannel));
245  entry->m_count = newcount;
246  channel = &entry->m_channelArray[id];
247  }
248  // compute the optimal buffer size
249  // The buffer size must be selected so that
250  // - it does not contain more than 1630 items (=1s of cache assuming 25 items per second)
251  // - it contains at least one item
252  // - it's not bigger than 256kb and preferably around 32kb
253  // - it a multiple of 4
254  unsigned int bufSize = 1630*(maxItemSize+4);
255  if (bufSize >= CACHE_DEFAULT_BUFFER_SIZE)
256  bufSize = CACHE_DEFAULT_BUFFER_SIZE;
257  if (bufSize < maxItemSize+16)
258  bufSize = maxItemSize+16;
259  bufSize = (bufSize + 3) & ~0x3;
260  // compute block size and offset bit mask
261  // the block size is computed so that
262  // - it is a power of 2
263  // - there is at least one item per block
264  // - there is no more than CACHE_LOOKUP_TABLE_SIZE blocks per buffer
265  unsigned int blockSize = bufSize/CACHE_LOOKUP_TABLE_SIZE;
266  if (blockSize < maxItemSize+12)
267  blockSize = maxItemSize+12;
268  // find the power of 2 that is immediately larger than blockSize
269  unsigned int m;
270  unsigned int pwr2Size = blockSize;
271  while ((m = (pwr2Size & (pwr2Size-1))) != 0)
272  pwr2Size = m;
273  blockSize = (pwr2Size < blockSize) ? pwr2Size<<1 : pwr2Size;
274  // convert byte size to word size because all positions and size are expressed in 32 bit words
275  blockSize >>= 2;
276  channel->m_blockSizeW = blockSize;
277  channel->m_bufferSizeW = bufSize>>2;
278  channel->m_firstBuffer = NULL;
279  channel->m_lastBuffer = NULL;
280  channel->m_busy = 1;
281  channel->initItem = NULL;
282  channel->m_maxItemSizeB = maxItemSize;
283  strncpy(channel->m_name, name, sizeof(channel->m_name));
284  channel->m_name[sizeof(channel->m_name)-1] = 0;
285  channel->m_positionToOffsetMaskW = (blockSize-1);
286  for (m=0; blockSize!=1; m++, blockSize>>=1);
287  channel->m_positionToBlockShiftW = m;
288  return (int)id;
289 }
290 
291 int Cache::deleteChannel(const void *device, int id)
292 {
293  CacheMap::iterator it = m_cache.find(device);
294  CacheEntry *entry;
295 
296  if (it == m_cache.end()) {
297  // device does not exist
298  return -1;
299  }
300  entry = it->second;
301  if (id < 0 || id >= (int)entry->m_count || !entry->m_channelArray[id].m_busy)
302  return -1;
303  entry->m_channelArray[id].clear();
304  entry->m_channelArray[id].m_busy = 0;
305  return 0;
306 }
307 
308 int Cache::deleteDevice(const void *device)
309 {
310  CacheMap::iterator it = m_cache.find(device);
311  CacheEntry *entry;
312 
313  if (it == m_cache.end()) {
314  // device does not exist
315  return -1;
316  }
317  entry = it->second;
318  delete entry;
319  m_cache.erase(it);
320  return 0;
321 }
322 
323 void Cache::clearCacheFrom(const void *device, CacheTS timestamp)
324 {
325  CacheMap::iterator it = (device) ? m_cache.find(device) : m_cache.begin();
326  CacheEntry *entry;
327  CacheChannel *channel;
328  CacheBuffer *buffer, *nextBuffer, *prevBuffer;
329  CacheItem *item, *prevItem, *nextItem;
330  unsigned int positionW, block;
331 
332  while (it != m_cache.end()) {
333  entry = it->second;
334  for (unsigned int ch=0; ch<entry->m_count; ch++) {
335  channel = &entry->m_channelArray[ch];
336  if (channel->m_busy) {
337  item = channel->findItemOrLater(timestamp, &buffer);
338  if (item ) {
339  if (!buffer) {
340  // this is possible if we return the special timestamp=0 item, delete all buffers
341  channel->clear();
342  } else {
343  // this item and all later items will be removed, clear any later buffer
344  while ((nextBuffer = buffer->m_next) != NULL) {
345  buffer->m_next = nextBuffer->m_next;
346  free(nextBuffer);
347  }
348  positionW = CACHE_ITEM_POSITIONW(buffer,item);
349  if (positionW == 0) {
350  // this item is the first one of the buffer, remove the buffer completely
351  // first find the buffer just before it
352  nextBuffer = channel->m_firstBuffer;
353  prevBuffer = NULL;
354  while (nextBuffer != buffer) {
355  prevBuffer = nextBuffer;
356  nextBuffer = nextBuffer->m_next;
357  // we must quit this loop before reaching the end of the list
358  assert(nextBuffer);
359  }
360  free(buffer);
361  buffer = prevBuffer;
362  if (buffer == NULL)
363  // this was also the first buffer
364  channel->m_firstBuffer = NULL;
365  } else {
366  // removing this item means finding the previous item to make it the last one
367  block = positionW>>channel->m_positionToBlockShiftW;
368  if (block == 0) {
369  // start from first item, we know it is not our item because positionW > 0
370  prevItem = &buffer->m_firstItem;
371  } else {
372  // no need to check the current block, it will point to our item or a later one
373  // but the previous block will be a good start for sure.
374  block--;
375  prevItem = CACHE_BLOCK_ITEM_ADDR(channel,buffer,block);
376  }
377  while ((nextItem = CACHE_NEXT_ITEM(prevItem)) < item)
378  prevItem = nextItem;
379  // we must have found our item
380  assert(nextItem==item);
381  // now set the buffer
382  buffer->m_lastItemPositionW = CACHE_ITEM_POSITIONW(buffer,prevItem);
383  buffer->m_firstFreePositionW = positionW;
384  buffer->m_lastTimestamp = buffer->m_firstTimestamp + prevItem->m_timeOffset;
385  block = buffer->m_lastItemPositionW>>channel->m_positionToBlockShiftW;
386  buffer->lookup[block].m_offsetW = buffer->m_lastItemPositionW&channel->m_positionToOffsetMaskW;
387  buffer->lookup[block].m_timeOffset = prevItem->m_timeOffset;
388  }
389  // set the channel
390  channel->m_lastBuffer = buffer;
391  if (buffer) {
392  channel->m_lastTimestamp = buffer->m_lastTimestamp;
393  channel->m_lastItemPositionW = buffer->m_lastItemPositionW;
394  }
395  }
396  }
397  }
398  }
399  if (device)
400  break;
401  ++it;
402  }
403 }
404 
405 void *Cache::addCacheItem(const void *device, int id, unsigned int timestamp, void *data, unsigned int length)
406 {
407  CacheMap::iterator it = m_cache.find(device);
408  CacheEntry *entry;
409  CacheChannel *channel;
411  CacheItem *item;
412  unsigned int positionW, sizeW, block;
413 
414  if (it == m_cache.end()) {
415  // device does not exist
416  return NULL;
417  }
418  entry = it->second;
419  if (id < 0 || id >= (int) entry->m_count || !entry->m_channelArray[id].m_busy)
420  return NULL;
421  channel = &entry->m_channelArray[id];
422  if (length > channel->m_maxItemSizeB)
423  return NULL;
424  if (timestamp == 0) {
425  // initial item, delete all buffers
426  channel->clear();
427  // and create initial item
428  item = NULL;
429  // we will allocate the memory, which is always pointer aligned => compute size
430  // with NULL will give same result.
431  sizeW = CACHE_ITEM_SIZEW(item,length);
432  item = (CacheItem*)calloc(sizeW, 4);
433  item->m_sizeW = sizeW;
434  channel->initItem = item;
435  } else {
436  if (!channel->m_lastBuffer) {
437  // no item in buffer, insert item at first position of first buffer
438  positionW = 0;
439  if ((buffer = channel->m_firstBuffer) == NULL) {
440  buffer = channel->allocBuffer();
441  channel->m_firstBuffer = buffer;
442  }
443  } else if (timestamp > channel->m_lastTimestamp) {
444  // this is the normal case: we are writing past lastest timestamp
445  buffer = channel->m_lastBuffer;
446  positionW = buffer->m_firstFreePositionW;
447  } else if (timestamp == channel->m_lastTimestamp) {
448  // common case, rewriting the last timestamp, just reuse the last position
449  buffer = channel->m_lastBuffer;
450  positionW = channel->m_lastItemPositionW;
451  } else {
452  // general case, write in the middle of the buffer, locate the timestamp
453  // (or the timestamp just after), clear this item and all future items,
454  // and write at that position
455  item = channel->findItemOrLater(timestamp, &buffer);
456  if (item == NULL) {
457  // this should not happen
458  return NULL;
459  }
460  // this item will become the last one of this channel, clear any later buffer
461  while ((next = buffer->m_next) != NULL) {
462  buffer->m_next = next->m_next;
463  free(next);
464  }
465  // no need to update the buffer, this will be done when the item is written
466  positionW = CACHE_ITEM_POSITIONW(buffer,item);
467  }
468  item = CACHE_ITEM_ADDR(buffer,positionW);
469  sizeW = CACHE_ITEM_SIZEW(item,length);
470  // we have positionW pointing where we can put the item
471  // before we do that we have to check if we can:
472  // - enough room
473  // - timestamp not too late
474  if ((positionW+sizeW > channel->m_bufferSizeW) ||
475  (positionW > 0 && timestamp >= buffer->m_firstTimestamp+0x10000)) {
476  // we must allocate a new buffer to store this item
477  // but before we must make sure that the current buffer is consistent
478  if (positionW != buffer->m_firstFreePositionW) {
479  // This means that we were trying to write in the middle of the buffer.
480  // We must set the buffer right with positionW being the last position
481  // and find the item before positionW to make it the last.
482  block = positionW>>channel->m_positionToBlockShiftW;
483  CacheItem *previousItem, *nextItem;
484  if (block == 0) {
485  // start from first item, we know it is not our item because positionW > 0
486  previousItem = &buffer->m_firstItem;
487  } else {
488  // no need to check the current block, it will point to our item or a later one
489  // but the previous block will be a good start for sure.
490  block--;
491  previousItem = CACHE_BLOCK_ITEM_ADDR(channel,buffer,block);
492  }
493  while ((nextItem = CACHE_NEXT_ITEM(previousItem)) < item)
494  previousItem = nextItem;
495  // we must have found our item
496  assert(nextItem==item);
497  // now set the buffer
498  buffer->m_lastItemPositionW = CACHE_ITEM_POSITIONW(buffer,previousItem);
499  buffer->m_firstFreePositionW = positionW;
500  buffer->m_lastTimestamp = buffer->m_firstTimestamp + previousItem->m_timeOffset;
501  block = buffer->m_lastItemPositionW>>channel->m_positionToBlockShiftW;
502  buffer->lookup[block].m_offsetW = buffer->m_lastItemPositionW&channel->m_positionToOffsetMaskW;
503  buffer->lookup[block].m_timeOffset = previousItem->m_timeOffset;
504  // and also the channel, just in case
505  channel->m_lastBuffer = buffer;
506  channel->m_lastTimestamp = buffer->m_lastTimestamp;
507  channel->m_lastItemPositionW = buffer->m_lastItemPositionW;
508  }
509  // now allocate a new buffer
510  buffer->m_next = channel->allocBuffer();
511  if (buffer->m_next == NULL)
512  return NULL;
513  buffer = buffer->m_next;
514  positionW = 0;
515  item = &buffer->m_firstItem;
516  sizeW = CACHE_ITEM_SIZEW(item,length);
517  }
518  // all check passed, ready to write the item
519  item->m_sizeW = sizeW;
520  if (positionW == 0) {
521  item->m_timeOffset = 0;
522  buffer->m_firstTimestamp = timestamp;
523  } else {
524  item->m_timeOffset = (unsigned short)(timestamp-buffer->m_firstTimestamp);
525  }
526  buffer->m_lastItemPositionW = positionW;
527  buffer->m_firstFreePositionW = positionW+sizeW;
528  buffer->m_lastTimestamp = timestamp;
529  block = positionW>>channel->m_positionToBlockShiftW;
530  buffer->lookup[block].m_offsetW = positionW&channel->m_positionToOffsetMaskW;
531  buffer->lookup[block].m_timeOffset = item->m_timeOffset;
532  buffer->m_lastItemPositionW = CACHE_ITEM_POSITIONW(buffer,item);
533  buffer->m_firstFreePositionW = buffer->m_lastItemPositionW+item->m_sizeW;
534  channel->m_lastBuffer = buffer;
535  channel->m_lastItemPositionW = positionW;
536  channel->m_lastTimestamp = timestamp;
537  }
538  // now copy the item
539  void *itemData = CACHE_ITEM_DATA_POINTER(item);
540  if (data)
541  memcpy(itemData, data, length);
542  return itemData;
543 }
544 
545 const void *Cache::getPreviousCacheItem(const void *device, int id, unsigned int *timestamp)
546 {
547  CacheMap::iterator it;
548  CacheEntry *entry;
549  CacheChannel *channel;
551  CacheItem *item;
552 
553  if (device) {
554  it = m_cache.find(device);
555  } else {
556  it = m_cache.begin();
557  }
558  if (it == m_cache.end()) {
559  // device does not exist
560  return NULL;
561  }
562  entry = it->second;
563  if (id < 0 || id >= (int) entry->m_count || !entry->m_channelArray[id].m_busy)
564  return NULL;
565  channel = &entry->m_channelArray[id];
566  if ((item = channel->findItemEarlier(*timestamp,&buffer)) == NULL)
567  return NULL;
568  *timestamp = (buffer) ? buffer->m_firstTimestamp+item->m_timeOffset : 0;
569  return CACHE_ITEM_DATA_POINTER(item);
570 }
571 
572 const CacheItem *Cache::getCurrentCacheItemInternal(const void *device, int id, CacheTS timestamp)
573 {
574  CacheMap::iterator it = m_cache.find(device);
575  CacheEntry *entry;
576  CacheChannel *channel;
578  CacheItem *item;
579 
580  if (it == m_cache.end()) {
581  // device does not exist
582  return NULL;
583  }
584  entry = it->second;
585  if (id < 0 || id >= (int) entry->m_count || !entry->m_channelArray[id].m_busy)
586  return NULL;
587  channel = &entry->m_channelArray[id];
588  if ((item = channel->findItemOrLater(timestamp,&buffer)) == NULL)
589  return NULL;
590  if (buffer && buffer->m_firstTimestamp+item->m_timeOffset != timestamp)
591  return NULL;
592  return item;
593 }
594 
595 const void *Cache::getCurrentCacheItem(const void *device, int channel, unsigned int timestamp)
596 {
597  const CacheItem *item = getCurrentCacheItemInternal(device, channel, timestamp);
598  return (item) ? CACHE_ITEM_DATA_POINTER(item) : NULL;
599 }
600 
601 double *Cache::addCacheVectorIfDifferent(const void *device, int channel, CacheTS timestamp, double *newdata, unsigned int length, double threshold)
602 {
603  const CacheItem *item = getCurrentCacheItemInternal(device, channel, timestamp);
604  unsigned int sizeW = CACHE_ITEM_SIZEW(item,length*sizeof(double));
605  if (!item || item->m_sizeW != sizeW)
606  return (double*)addCacheItem(device, channel, timestamp, newdata, length*sizeof(double));
607  double *olddata = (double*)CACHE_ITEM_DATA_POINTER(item);
608  if (!length)
609  return olddata;
610  double *ref = olddata;
611  double *v = newdata;
612  unsigned int i;
613  for (i=length; i>0; --i) {
614  if (fabs(*v-*ref) > threshold)
615  break;
616  *ref++ = *v++;
617  }
618  if (i)
619  olddata = (double*)addCacheItem(device, channel, timestamp, newdata, length*sizeof(double));
620  return olddata;
621 }
622 
623 }
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:116
#define CACHE_BLOCK_ITEM_ADDR(chan, buf, block)
Definition: Cache.hpp:28
#define CACHE_ITEM_DATA_POINTER(item)
Definition: Cache.hpp:23
#define CACHE_CHANNEL_EXTEND_SIZE
Definition: Cache.hpp:17
#define CACHE_DEFAULT_BUFFER_SIZE
Definition: Cache.hpp:16
#define CACHE_ITEM_POSITIONW(buf, item)
Definition: Cache.hpp:30
#define CACHE_BUFFER_HEADER_SIZE
Definition: Cache.hpp:217
#define CACHE_LOOKUP_TABLE_SIZE
Definition: Cache.hpp:15
#define CACHE_NEXT_ITEM(item)
Definition: Cache.hpp:27
#define CACHE_ITEM_ADDR(buf, pos)
Definition: Cache.hpp:29
#define CACHE_ITEM_SIZEW(item, length)
Definition: Cache.hpp:25
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
const void * getCurrentCacheItem(const void *device, int channel, CacheTS timestamp)
Definition: Cache.cpp:595
void clearCacheFrom(const void *device, CacheTS timestamp)
Definition: Cache.cpp:323
int deleteChannel(const void *device, int channel)
Definition: Cache.cpp:291
int addChannel(const void *device, const char *name, unsigned int maxItemSize)
Definition: Cache.cpp:203
int deleteDevice(const void *device)
Definition: Cache.cpp:308
void * addCacheItem(const void *device, int channel, CacheTS timestamp, void *data, unsigned int length)
Definition: Cache.cpp:405
double * addCacheVectorIfDifferent(const void *device, int channel, CacheTS timestamp, double *data, unsigned int length, double threshold)
Definition: Cache.cpp:601
const void * getPreviousCacheItem(const void *device, int channel, CacheTS *timestamp)
Definition: Cache.cpp:545
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
static ulong * next
static void clear(Message *msg)
Definition: msgfmt.c:294
unsigned int CacheTS
Definition: Cache.hpp:32
CacheItem * _findBlock(CacheBuffer *buffer, unsigned short timeOffset, unsigned int *highBlock)
Definition: Cache.cpp:26
struct CacheBuffer * m_firstBuffer
Definition: Cache.hpp:155
unsigned int m_maxItemSizeB
Definition: Cache.hpp:161
unsigned int m_blockSizeW
Definition: Cache.hpp:163
CacheItem * initItem
Definition: Cache.hpp:154
struct CacheBuffer * m_lastBuffer
Definition: Cache.hpp:156
char m_name[32]
Definition: Cache.hpp:157
CacheBuffer * allocBuffer()
Definition: Cache.cpp:89
unsigned char m_positionToBlockShiftW
Definition: Cache.hpp:159
unsigned int m_lastItemPositionW
Definition: Cache.hpp:165
unsigned int m_bufferSizeW
Definition: Cache.hpp:162
unsigned char m_busy
Definition: Cache.hpp:158
CacheItem * findItemEarlier(unsigned int timestamp, CacheBuffer **rBuffer)
Definition: Cache.cpp:138
unsigned short m_positionToOffsetMaskW
Definition: Cache.hpp:160
CacheItem * findItemOrLater(unsigned int timestamp, CacheBuffer **rBuffer)
Definition: Cache.cpp:101
unsigned int m_lastTimestamp
Definition: Cache.hpp:164
unsigned int m_count
Definition: Cache.hpp:147
CacheChannel * m_channelArray
Definition: Cache.hpp:146
unsigned short m_timeOffset
Definition: Cache.hpp:186
unsigned short m_sizeW
Definition: Cache.hpp:187
ccl_device_inline float2 fabs(const float2 &a)