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