cache1.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  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. #define IS_ACTIVE_ELT(elt) (c->locks[elt] != 2)
  11. #define IS_NOT_ACTIVE_ELT(elt) (c->locks[elt] == 2)
  12. #define IS_LOCKED_ELT(elt) (c->locks[elt] == 1)
  13. #define IS_UNLOCKED_ELT(elt) (c->locks[elt] == 0)
  14. #define IS_NOT_IN_QUEUE_ELT(elt) (IS_LOCKED_ELT (elt))
  15. #define IS_IN_QUEUE_ELT(elt) (! IS_NOT_IN_QUEUE_ELT (elt))
  16. #define DEACTIVATE_ELT(elt) ((IS_LOCKED_ELT(elt) ? \
  17. (c->nofUnlocked)++ : (0)), \
  18. c->locks[elt] = 2)
  19. #define LOCK_ELT(elt) ((IS_LOCKED_ELT(elt) ? \
  20. (0) : (c->nofUnlocked)--), \
  21. (c->locks[elt] = 1))
  22. #define UNLOCK_ELT(elt) ((IS_LOCKED_ELT(elt) ? \
  23. (c->nofUnlocked)++ : (0)), \
  24. (c->locks[elt] = 0))
  25. #define ONE_UNLOCKED_ELT_ONLY (c->first == c->last)
  26. #define ARE_MIN_UNLOCKED (c->nofUnlocked <= c->minUnlocked)
  27. /*---------------------------------------------------------------------------*/
  28. void Rast3d_cache_reset(RASTER3D_cache * c)
  29. {
  30. int i;
  31. for (i = 0; i < c->nofElts; i++) {
  32. DEACTIVATE_ELT(i);
  33. c->next[i] = i + 1;
  34. c->prev[i] = i - 1;
  35. c->names[i] = -1;
  36. }
  37. c->prev[0] = c->next[c->nofElts - 1] = -1;
  38. c->first = 0;
  39. c->last = c->nofElts - 1;
  40. c->autoLock = 0;
  41. c->nofUnlocked = c->nofElts;
  42. c->minUnlocked = 1;
  43. Rast3d_cache_hash_reset(c->hash);
  44. }
  45. /*---------------------------------------------------------------------------*/
  46. static int cache_dummy_fun(int tileIndex, const void *tileBuf, void *map)
  47. {
  48. return 1;
  49. }
  50. /*---------------------------------------------------------------------------*/
  51. void Rast3d_cache_dispose(RASTER3D_cache * c)
  52. {
  53. if (c == NULL)
  54. return;
  55. Rast3d_cache_hash_dispose(c->hash);
  56. if (c->elts != NULL)
  57. Rast3d_free(c->elts);
  58. if (c->names != NULL)
  59. Rast3d_free(c->names);
  60. if (c->locks != NULL)
  61. Rast3d_free(c->locks);
  62. if (c->next != NULL)
  63. Rast3d_free(c->next);
  64. if (c->prev != NULL)
  65. Rast3d_free(c->prev);
  66. Rast3d_free(c);
  67. }
  68. /*---------------------------------------------------------------------------*/
  69. void *Rast3d_cache_new(int nofElts, int sizeOfElts, int nofNames,
  70. int (*eltRemoveFun) (), void *eltRemoveFunData,
  71. int (*eltLoadFun) (), void *eltLoadFunData)
  72. {
  73. RASTER3D_cache *tmp;
  74. int i;
  75. tmp = Rast3d_malloc(sizeof(RASTER3D_cache));
  76. if (tmp == NULL) {
  77. Rast3d_error("Rast3d_cache_new: error in Rast3d_malloc");
  78. return (void *)NULL;
  79. }
  80. tmp->hash = NULL;
  81. tmp->nofElts = nofElts;
  82. tmp->eltSize = sizeOfElts;
  83. tmp->elts = Rast3d_malloc(tmp->eltSize * tmp->nofElts);
  84. tmp->names = Rast3d_malloc(sizeof(int) * tmp->nofElts);
  85. tmp->locks = Rast3d_malloc(tmp->nofElts);
  86. tmp->next = Rast3d_malloc(sizeof(int) * tmp->nofElts);
  87. tmp->prev = Rast3d_malloc(sizeof(int) * tmp->nofElts);
  88. if ((tmp->elts == NULL) || (tmp->names == NULL) || (tmp->locks == NULL) ||
  89. (tmp->next == NULL) || (tmp->prev == NULL)) {
  90. Rast3d_cache_dispose(tmp);
  91. Rast3d_error("Rast3d_cache_new: error in Rast3d_malloc");
  92. return (void *)NULL;
  93. }
  94. /* Init the cache lock */
  95. for(i = 0; i < tmp->nofElts; i++)
  96. tmp->locks[i] = 0;
  97. tmp->eltRemoveFun = eltRemoveFun;
  98. tmp->eltRemoveFunData = eltRemoveFunData;
  99. tmp->eltLoadFun = eltLoadFun;
  100. tmp->eltLoadFunData = eltLoadFunData;
  101. tmp->hash = Rast3d_cache_hash_new(nofNames);
  102. if (tmp->hash == NULL) {
  103. Rast3d_cache_dispose(tmp);
  104. Rast3d_error("Rast3d_cache_new: error in Rast3d_cache_hash_new");
  105. return (void *)NULL;
  106. }
  107. Rast3d_cache_reset(tmp);
  108. return tmp;
  109. }
  110. /*---------------------------------------------------------------------------*/
  111. void
  112. Rast3d_cache_set_remove_fun(RASTER3D_cache * c, int (*eltRemoveFun) (),
  113. void *eltRemoveFunData)
  114. {
  115. c->eltRemoveFun = eltRemoveFun;
  116. c->eltRemoveFunData = eltRemoveFunData;
  117. }
  118. /*---------------------------------------------------------------------------*/
  119. void
  120. Rast3d_cache_set_load_fun(RASTER3D_cache * c, int (*eltLoadFun) (),
  121. void *eltLoadFunData)
  122. {
  123. c->eltLoadFun = eltLoadFun;
  124. c->eltLoadFunData = eltLoadFunData;
  125. }
  126. /*---------------------------------------------------------------------------*/
  127. void *Rast3d_cache_new_read(int nofElts, int sizeOfElts, int nofNames,
  128. read_fn * eltLoadFun, void *eltLoadFunData)
  129. {
  130. return Rast3d_cache_new(nofElts, sizeOfElts, nofNames,
  131. cache_dummy_fun, NULL, eltLoadFun, eltLoadFunData);
  132. }
  133. /*---------------------------------------------------------------------------*/
  134. static void cache_queue_dequeue(RASTER3D_cache * c, int index)
  135. {
  136. if (IS_NOT_IN_QUEUE_ELT(index))
  137. Rast3d_fatal_error("cache_queue_dequeue: index not in queue");
  138. if (index == c->first)
  139. c->first = c->next[index];
  140. if (index == c->last)
  141. c->last = c->prev[index];
  142. if (c->next[index] != -1)
  143. c->prev[c->next[index]] = c->prev[index];
  144. if (c->prev[index] != -1)
  145. c->next[c->prev[index]] = c->next[index];
  146. c->next[index] = c->prev[index] = -1;
  147. }
  148. /*---------------------------------------------------------------------------*/
  149. static void cache_queue_enqueue(RASTER3D_cache * c, int left, int index)
  150. {
  151. if (IS_IN_QUEUE_ELT(index))
  152. Rast3d_fatal_error("cache_queue_enqueue: index already in queue");
  153. if (c->first == -1) {
  154. if (left != c->last)
  155. Rast3d_fatal_error("cache_queue_enqueue: position out of range");
  156. c->first = c->last = index;
  157. return;
  158. }
  159. if (left >= 0 && IS_NOT_IN_QUEUE_ELT(left))
  160. Rast3d_fatal_error("cache_queue_enqueue: position not in queue");
  161. if (left == -1) {
  162. c->next[index] = c->first;
  163. c->prev[c->first] = index;
  164. c->first = index;
  165. return;
  166. }
  167. c->prev[index] = left;
  168. if (c->next[left] == -1) {
  169. c->next[left] = index;
  170. c->last = index;
  171. return;
  172. }
  173. c->prev[c->next[left]] = index;
  174. c->next[index] = c->next[left];
  175. c->next[left] = index;
  176. }
  177. /*---------------------------------------------------------------------------*/
  178. static int cache_queue_get_top(RASTER3D_cache * c)
  179. {
  180. int top;
  181. top = c->first;
  182. cache_queue_dequeue(c, c->first);
  183. return top;
  184. }
  185. /*---------------------------------------------------------------------------*/
  186. static void cache_queue_append(RASTER3D_cache * c, int index)
  187. {
  188. cache_queue_enqueue(c, c->last, index);
  189. }
  190. /*---------------------------------------------------------------------------*/
  191. static void cache_queue_preppend(RASTER3D_cache * c, int index)
  192. {
  193. cache_queue_enqueue(c, -1, index);
  194. }
  195. /*---------------------------------------------------------------------------*/
  196. /*---------------------------------------------------------------------------*/
  197. /* EXPORTED FUNCTIONS */
  198. /*---------------------------------------------------------------------------*/
  199. /*---------------------------------------------------------------------------*/
  200. int Rast3d_cache_lock(RASTER3D_cache * c, int name)
  201. {
  202. int index;
  203. index = Rast3d_cache_hash_name2index(c->hash, name);
  204. if (index == -1) {
  205. Rast3d_error("Rast3d_cache_lock: name not in cache");
  206. return 0;
  207. }
  208. if (IS_LOCKED_ELT(index))
  209. return 1;
  210. if (ONE_UNLOCKED_ELT_ONLY)
  211. return -1;
  212. if (ARE_MIN_UNLOCKED)
  213. return -1;
  214. cache_queue_dequeue(c, index);
  215. LOCK_ELT(index);
  216. return 1;
  217. }
  218. /*---------------------------------------------------------------------------*/
  219. void Rast3d_cache_lock_intern(RASTER3D_cache * c, int index)
  220. {
  221. if (IS_LOCKED_ELT(index))
  222. return;
  223. cache_queue_dequeue(c, index);
  224. LOCK_ELT(index);
  225. }
  226. /*---------------------------------------------------------------------------*/
  227. int Rast3d_cache_unlock(RASTER3D_cache * c, int name)
  228. {
  229. int index;
  230. index = Rast3d_cache_hash_name2index(c->hash, name);
  231. if (index == -1) {
  232. Rast3d_error("Rast3d_cache_unlock: name not in cache");
  233. return 0;
  234. }
  235. if (IS_UNLOCKED_ELT(index))
  236. return 1;
  237. cache_queue_append(c, index);
  238. UNLOCK_ELT(index);
  239. return 1;
  240. }
  241. /*---------------------------------------------------------------------------*/
  242. int Rast3d_cache_unlock_all(RASTER3D_cache * c)
  243. {
  244. int index;
  245. for (index = 0; index < c->nofElts; index++)
  246. if (IS_LOCKED_ELT(index))
  247. if (!Rast3d_cache_unlock(c, c->names[index])) {
  248. Rast3d_error("Rast3d_cache_unlock_all: error in Rast3d_cache_unlock");
  249. return 0;
  250. }
  251. return 1;
  252. }
  253. /*---------------------------------------------------------------------------*/
  254. int Rast3d_cache_lock_all(RASTER3D_cache * c)
  255. {
  256. int index;
  257. for (index = 0; index < c->nofElts; index++)
  258. if (IS_UNLOCKED_ELT(index))
  259. Rast3d_cache_lock_intern(c, index);
  260. return 1;
  261. }
  262. /*---------------------------------------------------------------------------*/
  263. void Rast3d_cache_autolock_on(RASTER3D_cache * c)
  264. {
  265. c->autoLock = 1;
  266. }
  267. /*---------------------------------------------------------------------------*/
  268. void Rast3d_cache_autolock_off(RASTER3D_cache * c)
  269. {
  270. c->autoLock = 0;
  271. }
  272. /*---------------------------------------------------------------------------*/
  273. void Rast3d_cache_set_min_unlock(RASTER3D_cache * c, int nofMinUnLocked)
  274. {
  275. c->minUnlocked = nofMinUnLocked;
  276. }
  277. /*---------------------------------------------------------------------------*/
  278. static int cache_remove_elt(RASTER3D_cache * c, int name, int doFlush)
  279. {
  280. int index;
  281. index = Rast3d_cache_hash_name2index(c->hash, name);
  282. if (index == -1) {
  283. Rast3d_error("Rast3d_cache_deactivate_elt : name not in cache");
  284. return 0;
  285. }
  286. if (IS_NOT_ACTIVE_ELT(index))
  287. return 1;
  288. if (IS_IN_QUEUE_ELT(index)) {
  289. cache_queue_dequeue(c, index);
  290. LOCK_ELT(index);
  291. }
  292. if (doFlush)
  293. if (!c->eltRemoveFun(name, c->elts + c->eltSize * index,
  294. c->eltRemoveFunData)) {
  295. Rast3d_error("cache_remove_elt: error in c->eltRemoveFun");
  296. return 0;
  297. }
  298. cache_queue_preppend(c, index);
  299. DEACTIVATE_ELT(index);
  300. Rast3d_cache_hash_remove_name(c->hash, name);
  301. return 1;
  302. }
  303. /*---------------------------------------------------------------------------*/
  304. int Rast3d_cache_remove_elt(RASTER3D_cache * c, int name)
  305. {
  306. if (!cache_remove_elt(c, name, 0)) {
  307. Rast3d_error("Rast3d_cache_remove_elt: error in cache_remove_elt");
  308. return 0;
  309. }
  310. return 1;
  311. }
  312. /*---------------------------------------------------------------------------*/
  313. int Rast3d_cache_flush(RASTER3D_cache * c, int name)
  314. {
  315. if (!cache_remove_elt(c, name, 1)) {
  316. Rast3d_error("Rast3d_cache_flush: error in cache_remove_elt");
  317. return 0;
  318. }
  319. return 1;
  320. }
  321. /*---------------------------------------------------------------------------*/
  322. int Rast3d_cache_remove_all(RASTER3D_cache * c)
  323. {
  324. int index;
  325. for (index = 0; index < c->nofElts; index++)
  326. if (IS_ACTIVE_ELT(index))
  327. if (!Rast3d_cache_remove_elt(c, c->names[index])) {
  328. Rast3d_error
  329. ("Rast3d_cache_remove_all: error in Rast3d_cache_remove_elt");
  330. return 0;
  331. }
  332. return 1;
  333. }
  334. /*---------------------------------------------------------------------------*/
  335. int Rast3d_cache_flush_all(RASTER3D_cache * c)
  336. {
  337. int index;
  338. for (index = 0; index < c->nofElts; index++)
  339. if (IS_ACTIVE_ELT(index))
  340. if (!Rast3d_cache_flush(c, c->names[index])) {
  341. Rast3d_error("Rast3d_cache_flush_all: error in Rast3d_cache_flush");
  342. return 0;
  343. }
  344. return 1;
  345. }
  346. /*---------------------------------------------------------------------------*/
  347. void *Rast3d_cache_elt_ptr(RASTER3D_cache * c, int name)
  348. {
  349. int index, oldName, doUnlock;
  350. index = Rast3d_cache_hash_name2index(c->hash, name);
  351. if (index != -1) {
  352. if (c->autoLock)
  353. if (IS_UNLOCKED_ELT(index) && (!ONE_UNLOCKED_ELT_ONLY) &&
  354. (!ARE_MIN_UNLOCKED))
  355. Rast3d_cache_lock_intern(c, index);
  356. return c->elts + c->eltSize * index;
  357. }
  358. index = c->first;
  359. if (IS_ACTIVE_ELT(index)) {
  360. oldName = c->names[index];
  361. Rast3d_cache_hash_remove_name(c->hash, oldName);
  362. if (!c->eltRemoveFun(oldName, c->elts + c->eltSize * index,
  363. c->eltRemoveFunData)) {
  364. Rast3d_error("Rast3d_cache_elt_ptr: error in c->eltRemoveFun");
  365. return NULL;
  366. }
  367. }
  368. Rast3d_cache_hash_load_name(c->hash, name, index);
  369. doUnlock = ((!c->autoLock) || ONE_UNLOCKED_ELT_ONLY || ARE_MIN_UNLOCKED);
  370. UNLOCK_ELT(index);
  371. c->names[index] = name;
  372. Rast3d_cache_lock_intern(c, index);
  373. if (doUnlock)
  374. if (!Rast3d_cache_unlock(c, name)) {
  375. Rast3d_error("Rast3d_cache_elt_ptr: error in Rast3d_cache_unlock");
  376. return NULL;
  377. }
  378. if (!c->eltLoadFun(name, c->elts + c->eltSize * index, c->eltLoadFunData)) {
  379. Rast3d_error("Rast3d_cache_elt_ptr: error in c->eltLoadFun");
  380. return NULL;
  381. }
  382. return c->elts + c->eltSize * index;
  383. }
  384. /*---------------------------------------------------------------------------*/
  385. int Rast3d_cache_load(RASTER3D_cache * c, int name)
  386. {
  387. if (Rast3d_cache_elt_ptr(c, name) == NULL) {
  388. Rast3d_error("Rast3d_cache_load: error in Rast3d_cache_elt_ptr");
  389. return 0;
  390. }
  391. return 1;
  392. }
  393. /*---------------------------------------------------------------------------*/
  394. int Rast3d_cache_get_elt(RASTER3D_cache * c, int name, void *dst)
  395. {
  396. const void *elt;
  397. elt = Rast3d_cache_elt_ptr(c, name);
  398. if (elt == NULL) {
  399. Rast3d_error("Rast3d_cache_get_elt: error in Rast3d_cache_elt_ptr");
  400. return 0;
  401. }
  402. memcpy(dst, elt, c->eltSize);
  403. return 1;
  404. }
  405. /*---------------------------------------------------------------------------*/
  406. int Rast3d_cache_put_elt(RASTER3D_cache * c, int name, const void *src)
  407. {
  408. void *elt;
  409. elt = Rast3d_cache_elt_ptr(c, name);
  410. if (elt == NULL) {
  411. Rast3d_error("Rast3d_cache_put_elt: error in Rast3d_cache_elt_ptr");
  412. return 0;
  413. }
  414. memcpy(elt, src, c->eltSize);
  415. return 1;
  416. }
  417. /*---------------------------------------------------------------------------*/
  418. /*---------------------------------------------------------------------------*/
  419. /* TEST FUNCTIONS */
  420. /*---------------------------------------------------------------------------*/
  421. /*---------------------------------------------------------------------------*/
  422. static void cache_test_print(RASTER3D_cache * c)
  423. {
  424. int i, al;
  425. int *a;
  426. al = c->autoLock;
  427. Rast3d_cache_autolock_off(c);
  428. printf("\n--------------------------------\n");
  429. for (i = 0; i < c->nofElts; i++) {
  430. printf("elt %d: ", i);
  431. if (IS_NOT_ACTIVE_ELT(i)) {
  432. printf("na\n");
  433. continue;
  434. }
  435. a = (int *)Rast3d_cache_elt_ptr(c, c->names[i]);
  436. /*Rast3d_cache_get_elt (c, c->names[i], a); */
  437. printf("name %d val %d %s\n", c->names[i], a[17],
  438. (IS_LOCKED_ELT(i) ? "locked" :
  439. IS_UNLOCKED_ELT(i) ? "unlocked" : ""));
  440. }
  441. printf("\n--------------------------------\n");
  442. if (al)
  443. Rast3d_cache_autolock_on(c);
  444. }
  445. /*---------------------------------------------------------------------------*/
  446. static int cache_test_flush_fun(int name, const void *eltPtr, void *data)
  447. {
  448. printf("flushing name %d value %d\n", name, ((const int *)eltPtr)[17]);
  449. return 0;
  450. }
  451. /*---------------------------------------------------------------------------*/
  452. typedef struct
  453. {
  454. int *value;
  455. int size;
  456. } cache_test_data_type;
  457. static int cache_test_load_fun(int name, void *eltPtr, void *data)
  458. {
  459. const void *src;
  460. printf("loading name %d value %d\n", name,
  461. ((cache_test_data_type *) data)->value[17]);
  462. src = ((cache_test_data_type *) data)->value;
  463. memcpy(eltPtr, src, ((cache_test_data_type *) data)->size);
  464. return 0;
  465. }
  466. /*---------------------------------------------------------------------------*/
  467. static cache_test_data_type ctd;
  468. static void cache_test_add(void *c, int name, int val)
  469. {
  470. static int firstTime = 1;
  471. if (firstTime) {
  472. ctd.value = Rast3d_malloc(((RASTER3D_cache *) c)->eltSize * sizeof(int));
  473. firstTime = 0;
  474. }
  475. ctd.value[17] = val;
  476. ctd.size = ((RASTER3D_cache *) c)->eltSize;
  477. Rast3d_cache_load(c, name);
  478. }
  479. /*---------------------------------------------------------------------------*/
  480. int MAIN()
  481. {
  482. void *c;
  483. c = Rast3d_cache_new(3, 76 * sizeof(int), 100000,
  484. cache_test_flush_fun, NULL, cache_test_load_fun, &ctd);
  485. Rast3d_cache_autolock_on(c);
  486. cache_test_print(c);
  487. cache_test_add(c, 1111, -11);
  488. cache_test_print(c);
  489. cache_test_add(c, 2222, -22);
  490. cache_test_print(c);
  491. cache_test_add(c, 3333, -33);
  492. cache_test_print(c);
  493. cache_test_add(c, 4444, -44);
  494. cache_test_print(c);
  495. Rast3d_cache_unlock_all(c);
  496. cache_test_print(c);
  497. Rast3d_cache_load(c, 2222);
  498. cache_test_print(c);
  499. cache_test_add(c, 5555, -55);
  500. cache_test_print(c);
  501. cache_test_add(c, 6666, -66);
  502. cache_test_print(c);
  503. cache_test_add(c, 7777, -77);
  504. cache_test_print(c);
  505. cache_test_add(c, 8888, -88);
  506. cache_test_print(c);
  507. cache_test_add(c, 9999, -99);
  508. cache_test_print(c);
  509. Rast3d_cache_flush(c, 9999);
  510. cache_test_print(c);
  511. Rast3d_cache_flush_all(c);
  512. cache_test_print(c);
  513. cache_test_add(c, 1111, -11);
  514. cache_test_print(c);
  515. cache_test_add(c, 2222, -22);
  516. cache_test_print(c);
  517. cache_test_add(c, 3333, -33);
  518. cache_test_print(c);
  519. Rast3d_cache_reset(c);
  520. cache_test_print(c);
  521. cache_test_add(c, 1111, -11);
  522. cache_test_print(c);
  523. cache_test_add(c, 2222, -22);
  524. cache_test_print(c);
  525. cache_test_add(c, 3333, -33);
  526. cache_test_print(c);
  527. return 0;
  528. }