GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddeab64dbf
Loading...
Searching...
No Matches
cache1.c
Go to the documentation of this file.
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <sys/types.h>
5#include <unistd.h>
6#include <grass/raster3d.h>
7#include "raster3d_intern.h"
8#include "cachehash.h"
9
10/*---------------------------------------------------------------------------*/
11
12#define IS_ACTIVE_ELT(elt) (c->locks[elt] != 2)
13#define IS_NOT_ACTIVE_ELT(elt) (c->locks[elt] == 2)
14#define IS_LOCKED_ELT(elt) (c->locks[elt] == 1)
15#define IS_UNLOCKED_ELT(elt) (c->locks[elt] == 0)
16#define IS_NOT_IN_QUEUE_ELT(elt) (IS_LOCKED_ELT(elt))
17#define IS_IN_QUEUE_ELT(elt) (!IS_NOT_IN_QUEUE_ELT(elt))
18
19#define DEACTIVATE_ELT(elt) \
20 ((IS_LOCKED_ELT(elt) ? (c->nofUnlocked)++ : (0)), c->locks[elt] = 2)
21#define LOCK_ELT(elt) \
22 ((IS_LOCKED_ELT(elt) ? (0) : (c->nofUnlocked)--), (c->locks[elt] = 1))
23#define UNLOCK_ELT(elt) \
24 ((IS_LOCKED_ELT(elt) ? (c->nofUnlocked)++ : (0)), (c->locks[elt] = 0))
25
26#define ONE_UNLOCKED_ELT_ONLY (c->first == c->last)
27#define ARE_MIN_UNLOCKED (c->nofUnlocked <= c->minUnlocked)
28
29/*---------------------------------------------------------------------------*/
30
32{
33 int i;
34
35 for (i = 0; i < c->nofElts; i++) {
37 c->next[i] = i + 1;
38 c->prev[i] = i - 1;
39 c->names[i] = -1;
40 }
41
42 c->prev[0] = c->next[c->nofElts - 1] = -1;
43 c->first = 0;
44 c->last = c->nofElts - 1;
45
46 c->autoLock = 0;
47 c->nofUnlocked = c->nofElts;
48 c->minUnlocked = 1;
49
51}
52
53/*---------------------------------------------------------------------------*/
54
55static int cache_dummy_fun(int tileIndex UNUSED, const void *tileBuf UNUSED,
56 void *map UNUSED)
57{
58 return 1;
59}
60
61/*---------------------------------------------------------------------------*/
62
64{
65 if (c == NULL)
66 return;
67
69
70 if (c->elts != NULL)
71 Rast3d_free(c->elts);
72 if (c->names != NULL)
74 if (c->locks != NULL)
76 if (c->next != NULL)
77 Rast3d_free(c->next);
78 if (c->prev != NULL)
79 Rast3d_free(c->prev);
80
81 Rast3d_free(c);
82}
83
84/*---------------------------------------------------------------------------*/
85
86void *Rast3d_cache_new(int nofElts, int sizeOfElts, int nofNames,
87 int (*eltRemoveFun)(int, const void *, void *),
88 void *eltRemoveFunData,
89 int (*eltLoadFun)(int, void *, void *),
90 void *eltLoadFunData)
91{
92 RASTER3D_cache *tmp;
93 int i;
94
95 tmp = Rast3d_malloc(sizeof(RASTER3D_cache));
96 if (tmp == NULL) {
97 Rast3d_error("Rast3d_cache_new: error in Rast3d_malloc");
98 return (void *)NULL;
99 }
100
101 tmp->hash = NULL;
102
103 tmp->nofElts = nofElts;
104 tmp->eltSize = sizeOfElts;
105 tmp->elts = Rast3d_malloc(tmp->eltSize * tmp->nofElts);
106 tmp->names = Rast3d_malloc(sizeof(int) * tmp->nofElts);
107 tmp->locks = Rast3d_malloc(tmp->nofElts);
108 tmp->next = Rast3d_malloc(sizeof(int) * tmp->nofElts);
109 tmp->prev = Rast3d_malloc(sizeof(int) * tmp->nofElts);
110
111 if ((tmp->elts == NULL) || (tmp->names == NULL) || (tmp->locks == NULL) ||
112 (tmp->next == NULL) || (tmp->prev == NULL)) {
113
115 Rast3d_error("Rast3d_cache_new: error in Rast3d_malloc");
116 return (void *)NULL;
117 }
118 /* Init the cache lock */
119 for (i = 0; i < tmp->nofElts; i++)
120 tmp->locks[i] = 0;
121
122 tmp->eltRemoveFun = eltRemoveFun;
123 tmp->eltRemoveFunData = eltRemoveFunData;
124 tmp->eltLoadFun = eltLoadFun;
125 tmp->eltLoadFunData = eltLoadFunData;
126
127 tmp->hash = Rast3d_cache_hash_new(nofNames);
128 if (tmp->hash == NULL) {
130 Rast3d_error("Rast3d_cache_new: error in Rast3d_cache_hash_new");
131 return (void *)NULL;
132 }
133
135
136 return tmp;
137}
138
139/*---------------------------------------------------------------------------*/
140
142 int (*eltRemoveFun)(int, const void *, void *),
143 void *eltRemoveFunData)
144{
145 c->eltRemoveFun = eltRemoveFun;
146 c->eltRemoveFunData = eltRemoveFunData;
147}
148
149/*---------------------------------------------------------------------------*/
150
152 int (*eltLoadFun)(int, void *, void *),
153 void *eltLoadFunData)
154{
155 c->eltLoadFun = eltLoadFun;
156 c->eltLoadFunData = eltLoadFunData;
157}
158
159/*---------------------------------------------------------------------------*/
160
161void *Rast3d_cache_new_read(int nofElts, int sizeOfElts, int nofNames,
162 read_fn *eltLoadFun, void *eltLoadFunData)
163{
164 return Rast3d_cache_new(nofElts, sizeOfElts, nofNames, cache_dummy_fun,
165 NULL, eltLoadFun, eltLoadFunData);
166}
167
168/*---------------------------------------------------------------------------*/
169
170static void cache_queue_dequeue(RASTER3D_cache *c, int index)
171{
172 if (IS_NOT_IN_QUEUE_ELT(index))
173 Rast3d_fatal_error("cache_queue_dequeue: index not in queue");
174
175 if (index == c->first)
176 c->first = c->next[index];
177 if (index == c->last)
178 c->last = c->prev[index];
179
180 if (c->next[index] != -1)
181 c->prev[c->next[index]] = c->prev[index];
182 if (c->prev[index] != -1)
183 c->next[c->prev[index]] = c->next[index];
184
185 c->next[index] = c->prev[index] = -1;
186}
187
188/*---------------------------------------------------------------------------*/
189
190static void cache_queue_enqueue(RASTER3D_cache *c, int left, int index)
191{
192 if (IS_IN_QUEUE_ELT(index))
193 Rast3d_fatal_error("cache_queue_enqueue: index already in queue");
194
195 if (c->first == -1) {
196 if (left != c->last)
197 Rast3d_fatal_error("cache_queue_enqueue: position out of range");
198
199 c->first = c->last = index;
200 return;
201 }
202
203 if (left >= 0 && IS_NOT_IN_QUEUE_ELT(left))
204 Rast3d_fatal_error("cache_queue_enqueue: position not in queue");
205
206 if (left == -1) {
207 c->next[index] = c->first;
208 c->prev[c->first] = index;
209 c->first = index;
210
211 return;
212 }
213
214 c->prev[index] = left;
215
216 if (c->next[left] == -1) {
217 c->next[left] = index;
218 c->last = index;
219
220 return;
221 }
222
223 c->prev[c->next[left]] = index;
224 c->next[index] = c->next[left];
225 c->next[left] = index;
226}
227
228/*---------------------------------------------------------------------------*/
229
230#if 0 /* unused */
232{
233 int top;
234
235 top = c->first;
236
237 cache_queue_dequeue(c, c->first);
238
239 return top;
240}
241#endif
242
243/*---------------------------------------------------------------------------*/
244
245static void cache_queue_append(RASTER3D_cache *c, int index)
246{
247 cache_queue_enqueue(c, c->last, index);
248}
249
250/*---------------------------------------------------------------------------*/
251
252static void cache_queue_preppend(RASTER3D_cache *c, int index)
253{
254 cache_queue_enqueue(c, -1, index);
255}
256
257/*---------------------------------------------------------------------------*/
258
259/*---------------------------------------------------------------------------*/
260
261/* EXPORTED FUNCTIONS */
262
263/*---------------------------------------------------------------------------*/
264
265/*---------------------------------------------------------------------------*/
266
268{
269 int index;
270
272 if (index == -1) {
273 Rast3d_error("Rast3d_cache_lock: name not in cache");
274 return 0;
275 }
276
277 if (IS_LOCKED_ELT(index))
278 return 1;
280 return -1;
282 return -1;
283
284 cache_queue_dequeue(c, index);
285 LOCK_ELT(index);
286
287 return 1;
288}
289
290/*---------------------------------------------------------------------------*/
291
293{
294 if (IS_LOCKED_ELT(index))
295 return;
296
297 cache_queue_dequeue(c, index);
298 LOCK_ELT(index);
299}
300
301/*---------------------------------------------------------------------------*/
302
304{
305 int index;
306
308 if (index == -1) {
309 Rast3d_error("Rast3d_cache_unlock: name not in cache");
310 return 0;
311 }
312
313 if (IS_UNLOCKED_ELT(index))
314 return 1;
315
316 cache_queue_append(c, index);
317 UNLOCK_ELT(index);
318
319 return 1;
320}
321
322/*---------------------------------------------------------------------------*/
323
325{
326 int index;
327
328 for (index = 0; index < c->nofElts; index++)
329 if (IS_LOCKED_ELT(index))
330 if (!Rast3d_cache_unlock(c, c->names[index])) {
332 "Rast3d_cache_unlock_all: error in Rast3d_cache_unlock");
333 return 0;
334 }
335
336 return 1;
337}
338
339/*---------------------------------------------------------------------------*/
340
342{
343 int index;
344
345 for (index = 0; index < c->nofElts; index++)
346 if (IS_UNLOCKED_ELT(index))
347 Rast3d_cache_lock_intern(c, index);
348
349 return 1;
350}
351
352/*---------------------------------------------------------------------------*/
353
355{
356 c->autoLock = 1;
357}
358
359/*---------------------------------------------------------------------------*/
360
362{
363 c->autoLock = 0;
364}
365
366/*---------------------------------------------------------------------------*/
367
372
373/*---------------------------------------------------------------------------*/
374
375static int cache_remove_elt(RASTER3D_cache *c, int name, int doFlush)
376{
377 int index;
378
380 if (index == -1) {
381 Rast3d_error("Rast3d_cache_deactivate_elt : name not in cache");
382 return 0;
383 }
384
385 if (IS_NOT_ACTIVE_ELT(index))
386 return 1;
387
388 if (IS_IN_QUEUE_ELT(index)) {
389 cache_queue_dequeue(c, index);
390 LOCK_ELT(index);
391 }
392
393 if (doFlush)
394 if (!c->eltRemoveFun(name, c->elts + c->eltSize * index,
395 c->eltRemoveFunData)) {
396 Rast3d_error("cache_remove_elt: error in c->eltRemoveFun");
397 return 0;
398 }
399
400 cache_queue_preppend(c, index);
401 DEACTIVATE_ELT(index);
402
404
405 return 1;
406}
407
408/*---------------------------------------------------------------------------*/
409
411{
412 if (!cache_remove_elt(c, name, 0)) {
413 Rast3d_error("Rast3d_cache_remove_elt: error in cache_remove_elt");
414 return 0;
415 }
416
417 return 1;
418}
419
420/*---------------------------------------------------------------------------*/
421
423{
424 if (!cache_remove_elt(c, name, 1)) {
425 Rast3d_error("Rast3d_cache_flush: error in cache_remove_elt");
426 return 0;
427 }
428
429 return 1;
430}
431
432/*---------------------------------------------------------------------------*/
433
435{
436 int index;
437
438 for (index = 0; index < c->nofElts; index++)
439 if (IS_ACTIVE_ELT(index))
440 if (!Rast3d_cache_remove_elt(c, c->names[index])) {
441 Rast3d_error("Rast3d_cache_remove_all: error in "
442 "Rast3d_cache_remove_elt");
443 return 0;
444 }
445
446 return 1;
447}
448
449/*---------------------------------------------------------------------------*/
450
452{
453 int index;
454
455 for (index = 0; index < c->nofElts; index++)
456 if (IS_ACTIVE_ELT(index))
457 if (!Rast3d_cache_flush(c, c->names[index])) {
459 "Rast3d_cache_flush_all: error in Rast3d_cache_flush");
460 return 0;
461 }
462
463 return 1;
464}
465
466/*---------------------------------------------------------------------------*/
467
469{
470 int index, oldName, doUnlock;
471
473
474 if (index != -1) {
475 if (c->autoLock)
476 if (IS_UNLOCKED_ELT(index) && (!ONE_UNLOCKED_ELT_ONLY) &&
478 Rast3d_cache_lock_intern(c, index);
479
480 return c->elts + c->eltSize * index;
481 }
482
483 index = c->first;
484 if (IS_ACTIVE_ELT(index)) {
485 oldName = c->names[index];
487 if (!c->eltRemoveFun(oldName, c->elts + c->eltSize * index,
488 c->eltRemoveFunData)) {
489 Rast3d_error("Rast3d_cache_elt_ptr: error in c->eltRemoveFun");
490 return NULL;
491 }
492 }
493
495
497
498 UNLOCK_ELT(index);
499 c->names[index] = name;
500 Rast3d_cache_lock_intern(c, index);
501
502 if (doUnlock)
503 if (!Rast3d_cache_unlock(c, name)) {
504 Rast3d_error("Rast3d_cache_elt_ptr: error in Rast3d_cache_unlock");
505 return NULL;
506 }
507
508 if (!c->eltLoadFun(name, c->elts + c->eltSize * index, c->eltLoadFunData)) {
509 Rast3d_error("Rast3d_cache_elt_ptr: error in c->eltLoadFun");
510 return NULL;
511 }
512
513 return c->elts + c->eltSize * index;
514}
515
516/*---------------------------------------------------------------------------*/
517
519{
520 if (Rast3d_cache_elt_ptr(c, name) == NULL) {
521 Rast3d_error("Rast3d_cache_load: error in Rast3d_cache_elt_ptr");
522 return 0;
523 }
524
525 return 1;
526}
527
528/*---------------------------------------------------------------------------*/
529
531{
532 const void *elt;
533
534 elt = Rast3d_cache_elt_ptr(c, name);
535 if (elt == NULL) {
536 Rast3d_error("Rast3d_cache_get_elt: error in Rast3d_cache_elt_ptr");
537 return 0;
538 }
539
540 memcpy(dst, elt, c->eltSize);
541
542 return 1;
543}
544
545/*---------------------------------------------------------------------------*/
546
547int Rast3d_cache_put_elt(RASTER3D_cache *c, int name, const void *src)
548{
549 void *elt;
550
551 elt = Rast3d_cache_elt_ptr(c, name);
552 if (elt == NULL) {
553 Rast3d_error("Rast3d_cache_put_elt: error in Rast3d_cache_elt_ptr");
554 return 0;
555 }
556
557 memcpy(elt, src, c->eltSize);
558
559 return 1;
560}
561
562/*---------------------------------------------------------------------------*/
563
564/*---------------------------------------------------------------------------*/
565
566/* TEST FUNCTIONS */
567
568/*---------------------------------------------------------------------------*/
569
570/*---------------------------------------------------------------------------*/
571
572static void cache_test_print(RASTER3D_cache *c)
573{
574 int i, al;
575 int *a;
576
577 al = c->autoLock;
579
580 printf("\n--------------------------------\n");
581 for (i = 0; i < c->nofElts; i++) {
582 printf("elt %d: ", i);
583 if (IS_NOT_ACTIVE_ELT(i)) {
584 printf("na\n");
585 continue;
586 }
587
588 a = (int *)Rast3d_cache_elt_ptr(c, c->names[i]);
589 /*Rast3d_cache_get_elt (c, c->names[i], a); */
590 printf("name %d val %d %s\n", c->names[i], a[17],
591 (IS_LOCKED_ELT(i) ? "locked"
592 : IS_UNLOCKED_ELT(i) ? "unlocked"
593 : ""));
594 }
595 printf("\n--------------------------------\n");
596
597 if (al)
599}
600
601/*---------------------------------------------------------------------------*/
602
603static int cache_test_flush_fun(int name, const void *eltPtr, void *data UNUSED)
604{
605 printf("flushing name %d value %d\n", name, ((const int *)eltPtr)[17]);
606 return 0;
607}
608
609/*---------------------------------------------------------------------------*/
610
611typedef struct {
612
613 int *value;
614 int size;
615
616} cache_test_data_type;
617
618static int cache_test_load_fun(int name, void *eltPtr, void *data)
619{
620 const void *src;
621
622 printf("loading name %d value %d\n", name,
623 ((cache_test_data_type *)data)->value[17]);
624
625 src = ((cache_test_data_type *)data)->value;
626 memcpy(eltPtr, src, ((cache_test_data_type *)data)->size);
627
628 return 0;
629}
630
631/*---------------------------------------------------------------------------*/
632
633static cache_test_data_type ctd;
634
635static void cache_test_add(void *c, int name, int val)
636{
637 static int firstTime = 1;
638
639 if (firstTime) {
640 ctd.value = Rast3d_malloc(((RASTER3D_cache *)c)->eltSize * sizeof(int));
641 firstTime = 0;
642 }
643
644 ctd.value[17] = val;
645 ctd.size = ((RASTER3D_cache *)c)->eltSize;
646
648}
649
650/*---------------------------------------------------------------------------*/
651
652int MAIN(void)
653{
654 void *c;
655
656 c = Rast3d_cache_new(3, 76 * sizeof(int), 100000, cache_test_flush_fun,
657 NULL, cache_test_load_fun, &ctd);
658
660 cache_test_print(c);
661 cache_test_add(c, 1111, -11);
662 cache_test_print(c);
663 cache_test_add(c, 2222, -22);
664 cache_test_print(c);
665 cache_test_add(c, 3333, -33);
666 cache_test_print(c);
667 cache_test_add(c, 4444, -44);
668 cache_test_print(c);
670 cache_test_print(c);
671 Rast3d_cache_load(c, 2222);
672 cache_test_print(c);
673 cache_test_add(c, 5555, -55);
674 cache_test_print(c);
675 cache_test_add(c, 6666, -66);
676 cache_test_print(c);
677 cache_test_add(c, 7777, -77);
678 cache_test_print(c);
679 cache_test_add(c, 8888, -88);
680 cache_test_print(c);
681 cache_test_add(c, 9999, -99);
682 cache_test_print(c);
683 Rast3d_cache_flush(c, 9999);
684 cache_test_print(c);
686 cache_test_print(c);
687 cache_test_add(c, 1111, -11);
688 cache_test_print(c);
689 cache_test_add(c, 2222, -22);
690 cache_test_print(c);
691 cache_test_add(c, 3333, -33);
692 cache_test_print(c);
694 cache_test_print(c);
695 cache_test_add(c, 1111, -11);
696 cache_test_print(c);
697 cache_test_add(c, 2222, -22);
698 cache_test_print(c);
699 cache_test_add(c, 3333, -33);
700 cache_test_print(c);
701
702 return 0;
703}
void * Rast3d_cache_elt_ptr(RASTER3D_cache *c, int name)
Definition cache1.c:468
int Rast3d_cache_lock(RASTER3D_cache *c, int name)
Definition cache1.c:267
#define IS_ACTIVE_ELT(elt)
Definition cache1.c:12
int Rast3d_cache_get_elt(RASTER3D_cache *c, int name, void *dst)
Definition cache1.c:530
void Rast3d_cache_reset(RASTER3D_cache *c)
Definition cache1.c:31
int MAIN(void)
Definition cache1.c:652
#define ONE_UNLOCKED_ELT_ONLY
Definition cache1.c:26
int Rast3d_cache_flush_all(RASTER3D_cache *c)
Definition cache1.c:451
#define IS_IN_QUEUE_ELT(elt)
Definition cache1.c:17
int Rast3d_cache_unlock_all(RASTER3D_cache *c)
Definition cache1.c:324
void Rast3d_cache_set_min_unlock(RASTER3D_cache *c, int nofMinUnLocked)
Definition cache1.c:368
int Rast3d_cache_remove_all(RASTER3D_cache *c)
Definition cache1.c:434
#define UNLOCK_ELT(elt)
Definition cache1.c:23
void Rast3d_cache_set_load_fun(RASTER3D_cache *c, int(*eltLoadFun)(int, void *, void *), void *eltLoadFunData)
Definition cache1.c:151
void Rast3d_cache_dispose(RASTER3D_cache *c)
Definition cache1.c:63
int Rast3d_cache_load(RASTER3D_cache *c, int name)
Definition cache1.c:518
void Rast3d_cache_autolock_on(RASTER3D_cache *c)
Definition cache1.c:354
void Rast3d_cache_set_remove_fun(RASTER3D_cache *c, int(*eltRemoveFun)(int, const void *, void *), void *eltRemoveFunData)
Definition cache1.c:141
int Rast3d_cache_put_elt(RASTER3D_cache *c, int name, const void *src)
Definition cache1.c:547
void * Rast3d_cache_new(int nofElts, int sizeOfElts, int nofNames, int(*eltRemoveFun)(int, const void *, void *), void *eltRemoveFunData, int(*eltLoadFun)(int, void *, void *), void *eltLoadFunData)
Definition cache1.c:86
#define ARE_MIN_UNLOCKED
Definition cache1.c:27
#define IS_NOT_IN_QUEUE_ELT(elt)
Definition cache1.c:16
int Rast3d_cache_unlock(RASTER3D_cache *c, int name)
Definition cache1.c:303
int Rast3d_cache_flush(RASTER3D_cache *c, int name)
Definition cache1.c:422
int Rast3d_cache_lock_all(RASTER3D_cache *c)
Definition cache1.c:341
#define DEACTIVATE_ELT(elt)
Definition cache1.c:19
#define IS_LOCKED_ELT(elt)
Definition cache1.c:14
void Rast3d_cache_autolock_off(RASTER3D_cache *c)
Definition cache1.c:361
#define IS_NOT_ACTIVE_ELT(elt)
Definition cache1.c:13
void Rast3d_cache_lock_intern(RASTER3D_cache *c, int index)
Definition cache1.c:292
void * Rast3d_cache_new_read(int nofElts, int sizeOfElts, int nofNames, read_fn *eltLoadFun, void *eltLoadFunData)
Definition cache1.c:161
int Rast3d_cache_remove_elt(RASTER3D_cache *c, int name)
Definition cache1.c:410
#define LOCK_ELT(elt)
Definition cache1.c:21
#define IS_UNLOCKED_ELT(elt)
Definition cache1.c:15
#define NULL
Definition ccmath.h:32
void Rast3d_free(void *)
Same as free (ptr).
void Rast3d_cache_hash_dispose(Rast3d_cache_hash *)
Definition cachehash.c:36
void Rast3d_cache_hash_remove_name(Rast3d_cache_hash *, int)
Definition cachehash.c:76
void * Rast3d_cache_hash_new(int)
Definition cachehash.c:50
void Rast3d_cache_hash_reset(Rast3d_cache_hash *)
Definition cachehash.c:24
void Rast3d_cache_hash_load_name(Rast3d_cache_hash *, int, int)
Definition cachehash.c:93
void * Rast3d_malloc(int)
Same as malloc (nBytes), except that in case of error Rast3d_error() is invoked.
void Rast3d_error(const char *,...) __attribute__((format(printf
int Rast3d_cache_hash_name2index(Rast3d_cache_hash *, int)
Definition cachehash.c:108
void Rast3d_fatal_error(const char *,...) __attribute__((format(printf
#define UNUSED
A macro for an attribute, if attached to a variable, indicating that the variable is not used.
Definition gis.h:46
const char * name
Definition named_colr.c:6
int read_fn(int, void *, void *)
Definition raster3d.h:255
void * eltRemoveFunData
Definition raster3d.h:213
int(* eltRemoveFun)(int, const void *, void *)
Definition raster3d.h:210
void * eltLoadFunData
Definition raster3d.h:218
int(* eltLoadFun)(int, void *, void *)
Definition raster3d.h:215