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