00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "queue.h"
00008 #include "core/alloc_func.hpp"
00009
00010
00011
00012
00013
00014
00015 static void InsSort_Clear(Queue* q, bool free_values)
00016 {
00017 InsSortNode* node = q->data.inssort.first;
00018 InsSortNode* prev;
00019
00020 while (node != NULL) {
00021 if (free_values) free(node->item);
00022 prev = node;
00023 node = node->next;
00024 free(prev);
00025 }
00026 q->data.inssort.first = NULL;
00027 }
00028
00029 static void InsSort_Free(Queue* q, bool free_values)
00030 {
00031 q->clear(q, free_values);
00032 }
00033
00034 static bool InsSort_Push(Queue* q, void* item, int priority)
00035 {
00036 InsSortNode* newnode = MallocT<InsSortNode>(1);
00037
00038 if (newnode == NULL) return false;
00039 newnode->item = item;
00040 newnode->priority = priority;
00041 if (q->data.inssort.first == NULL ||
00042 q->data.inssort.first->priority >= priority) {
00043 newnode->next = q->data.inssort.first;
00044 q->data.inssort.first = newnode;
00045 } else {
00046 InsSortNode* node = q->data.inssort.first;
00047 while (node != NULL) {
00048 if (node->next == NULL || node->next->priority >= priority) {
00049 newnode->next = node->next;
00050 node->next = newnode;
00051 break;
00052 }
00053 node = node->next;
00054 }
00055 }
00056 return true;
00057 }
00058
00059 static void* InsSort_Pop(Queue* q)
00060 {
00061 InsSortNode* node = q->data.inssort.first;
00062 void* result;
00063
00064 if (node == NULL) return NULL;
00065 result = node->item;
00066 q->data.inssort.first = q->data.inssort.first->next;
00067 assert(q->data.inssort.first == NULL || q->data.inssort.first->priority >= node->priority);
00068 free(node);
00069 return result;
00070 }
00071
00072 static bool InsSort_Delete(Queue* q, void* item, int priority)
00073 {
00074 return false;
00075 }
00076
00077 void init_InsSort(Queue* q)
00078 {
00079 q->push = InsSort_Push;
00080 q->pop = InsSort_Pop;
00081 q->del = InsSort_Delete;
00082 q->clear = InsSort_Clear;
00083 q->free = InsSort_Free;
00084 q->data.inssort.first = NULL;
00085 }
00086
00087
00088
00089
00090
00091
00092
00093 #define BINARY_HEAP_BLOCKSIZE (1 << BINARY_HEAP_BLOCKSIZE_BITS)
00094 #define BINARY_HEAP_BLOCKSIZE_MASK (BINARY_HEAP_BLOCKSIZE - 1)
00095
00096
00097
00098
00099
00100 #define BIN_HEAP_ARR(i) q->data.binaryheap.elements[((i) - 1) >> BINARY_HEAP_BLOCKSIZE_BITS][((i) - 1) & BINARY_HEAP_BLOCKSIZE_MASK]
00101
00102 static void BinaryHeap_Clear(Queue* q, bool free_values)
00103 {
00104
00105 uint i;
00106 uint j;
00107
00108 for (i = 0; i < q->data.binaryheap.blocks; i++) {
00109 if (q->data.binaryheap.elements[i] == NULL) {
00110
00111 break;
00112 }
00113
00114 if (free_values) {
00115 for (j = 0; j < (1 << BINARY_HEAP_BLOCKSIZE_BITS); j++) {
00116
00117 if ((q->data.binaryheap.size >> BINARY_HEAP_BLOCKSIZE_BITS) == i &&
00118 (q->data.binaryheap.size & BINARY_HEAP_BLOCKSIZE_MASK) == j) {
00119 break;
00120 }
00121 free(q->data.binaryheap.elements[i][j].item);
00122 }
00123 }
00124 if (i != 0) {
00125
00126 free(q->data.binaryheap.elements[i]);
00127 q->data.binaryheap.elements[i] = NULL;
00128 }
00129 }
00130 q->data.binaryheap.size = 0;
00131 q->data.binaryheap.blocks = 1;
00132 }
00133
00134 static void BinaryHeap_Free(Queue* q, bool free_values)
00135 {
00136 uint i;
00137
00138 q->clear(q, free_values);
00139 for (i = 0; i < q->data.binaryheap.blocks; i++) {
00140 if (q->data.binaryheap.elements[i] == NULL) break;
00141 free(q->data.binaryheap.elements[i]);
00142 }
00143 free(q->data.binaryheap.elements);
00144 }
00145
00146 static bool BinaryHeap_Push(Queue* q, void* item, int priority)
00147 {
00148 #ifdef QUEUE_DEBUG
00149 printf("[BinaryHeap] Pushing an element. There are %d elements left\n", q->data.binaryheap.size);
00150 #endif
00151
00152 if (q->data.binaryheap.size == q->data.binaryheap.max_size) return false;
00153 assert(q->data.binaryheap.size < q->data.binaryheap.max_size);
00154
00155 if (q->data.binaryheap.elements[q->data.binaryheap.size >> BINARY_HEAP_BLOCKSIZE_BITS] == NULL) {
00156
00157 assert((q->data.binaryheap.size & BINARY_HEAP_BLOCKSIZE_MASK) == 0);
00158 q->data.binaryheap.elements[q->data.binaryheap.size >> BINARY_HEAP_BLOCKSIZE_BITS] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
00159 q->data.binaryheap.blocks++;
00160 #ifdef QUEUE_DEBUG
00161 printf("[BinaryHeap] Increasing size of elements to %d nodes\n", q->data.binaryheap.blocks * BINARY_HEAP_BLOCKSIZE);
00162 #endif
00163 }
00164
00165
00166 BIN_HEAP_ARR(q->data.binaryheap.size + 1).priority = priority;
00167 BIN_HEAP_ARR(q->data.binaryheap.size + 1).item = item;
00168 q->data.binaryheap.size++;
00169
00170
00171
00172 {
00173 BinaryHeapNode temp;
00174 int i;
00175 int j;
00176
00177 i = q->data.binaryheap.size;
00178 while (i > 1) {
00179
00180 j = i / 2;
00181
00182 if (BIN_HEAP_ARR(i).priority <= BIN_HEAP_ARR(j).priority) {
00183 temp = BIN_HEAP_ARR(j);
00184 BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i);
00185 BIN_HEAP_ARR(i) = temp;
00186 i = j;
00187 } else {
00188
00189 break;
00190 }
00191 }
00192 }
00193
00194 return true;
00195 }
00196
00197 static bool BinaryHeap_Delete(Queue* q, void* item, int priority)
00198 {
00199 uint i = 0;
00200
00201 #ifdef QUEUE_DEBUG
00202 printf("[BinaryHeap] Deleting an element. There are %d elements left\n", q->data.binaryheap.size);
00203 #endif
00204
00205
00206 do {
00207 if (BIN_HEAP_ARR(i + 1).item == item) break;
00208 i++;
00209 } while (i < q->data.binaryheap.size);
00210
00211 if (i == q->data.binaryheap.size) return false;
00212
00213
00214 q->data.binaryheap.size--;
00215 BIN_HEAP_ARR(i + 1) = BIN_HEAP_ARR(q->data.binaryheap.size + 1);
00216
00217
00218
00219 {
00220 uint j;
00221 BinaryHeapNode temp;
00222
00223
00224
00225 i++;
00226
00227 for (;;) {
00228 j = i;
00229
00230 if (2 * j + 1 <= q->data.binaryheap.size) {
00231
00232 if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j;
00233
00234
00235 if (BIN_HEAP_ARR(i).priority >= BIN_HEAP_ARR(2 * j + 1).priority) i = 2 * j + 1;
00236
00237 } else if (2 * j <= q->data.binaryheap.size) {
00238 if (BIN_HEAP_ARR(j).priority >= BIN_HEAP_ARR(2 * j).priority) i = 2 * j;
00239 }
00240
00241
00242 if (i != j) {
00243 temp = BIN_HEAP_ARR(j);
00244 BIN_HEAP_ARR(j) = BIN_HEAP_ARR(i);
00245 BIN_HEAP_ARR(i) = temp;
00246 } else {
00247
00248 break;
00249 }
00250 }
00251 }
00252
00253 return true;
00254 }
00255
00256 static void* BinaryHeap_Pop(Queue* q)
00257 {
00258 void* result;
00259
00260 #ifdef QUEUE_DEBUG
00261 printf("[BinaryHeap] Popping an element. There are %d elements left\n", q->data.binaryheap.size);
00262 #endif
00263
00264 if (q->data.binaryheap.size == 0) return NULL;
00265
00266
00267 result = BIN_HEAP_ARR(1).item;
00268
00269 BinaryHeap_Delete(q, BIN_HEAP_ARR(1).item, BIN_HEAP_ARR(1).priority);
00270
00271 return result;
00272 }
00273
00274 void init_BinaryHeap(Queue* q, uint max_size)
00275 {
00276 assert(q != NULL);
00277 q->push = BinaryHeap_Push;
00278 q->pop = BinaryHeap_Pop;
00279 q->del = BinaryHeap_Delete;
00280 q->clear = BinaryHeap_Clear;
00281 q->free = BinaryHeap_Free;
00282 q->data.binaryheap.max_size = max_size;
00283 q->data.binaryheap.size = 0;
00284
00285
00286 q->data.binaryheap.elements = CallocT<BinaryHeapNode*>((max_size - 1) / BINARY_HEAP_BLOCKSIZE + 1);
00287 q->data.binaryheap.elements[0] = MallocT<BinaryHeapNode>(BINARY_HEAP_BLOCKSIZE);
00288 q->data.binaryheap.blocks = 1;
00289 #ifdef QUEUE_DEBUG
00290 printf("[BinaryHeap] Initial size of elements is %d nodes\n", BINARY_HEAP_BLOCKSIZE);
00291 #endif
00292 }
00293
00294
00295 #undef BIN_HEAP_ARR
00296
00297
00298
00299
00300
00301 void init_Hash(Hash* h, Hash_HashProc* hash, uint num_buckets)
00302 {
00303
00304 uint i;
00305
00306 assert(h != NULL);
00307 #ifdef HASH_DEBUG
00308 debug("Allocated hash: %p", h);
00309 #endif
00310 h->hash = hash;
00311 h->size = 0;
00312 h->num_buckets = num_buckets;
00313 h->buckets = (HashNode*)MallocT<byte>(num_buckets * (sizeof(*h->buckets) + sizeof(*h->buckets_in_use)));
00314 #ifdef HASH_DEBUG
00315 debug("Buckets = %p", h->buckets);
00316 #endif
00317 h->buckets_in_use = (bool*)(h->buckets + num_buckets);
00318 for (i = 0; i < num_buckets; i++) h->buckets_in_use[i] = false;
00319 }
00320
00321
00322 void delete_Hash(Hash* h, bool free_values)
00323 {
00324 uint i;
00325
00326
00327 for (i = 0; i < h->num_buckets; i++) {
00328 if (h->buckets_in_use[i]) {
00329 HashNode* node;
00330
00331
00332 if (free_values) free(h->buckets[i].value);
00333 node = h->buckets[i].next;
00334 while (node != NULL) {
00335 HashNode* prev = node;
00336
00337 node = node->next;
00338
00339 if (free_values) free(prev->value);
00340
00341 free(prev);
00342 }
00343 }
00344 }
00345 free(h->buckets);
00346
00347
00348 #ifdef HASH_DEBUG
00349 debug("Freeing Hash: %p", h);
00350 #endif
00351 }
00352
00353 #ifdef HASH_STATS
00354 static void stat_Hash(const Hash* h)
00355 {
00356 uint used_buckets = 0;
00357 uint max_collision = 0;
00358 uint max_usage = 0;
00359 uint usage[200];
00360 uint i;
00361
00362 for (i = 0; i < lengthof(usage); i++) usage[i] = 0;
00363 for (i = 0; i < h->num_buckets; i++) {
00364 uint collision = 0;
00365 if (h->buckets_in_use[i]) {
00366 const HashNode* node;
00367
00368 used_buckets++;
00369 for (node = &h->buckets[i]; node != NULL; node = node->next) collision++;
00370 if (collision > max_collision) max_collision = collision;
00371 }
00372 if (collision >= lengthof(usage)) collision = lengthof(usage) - 1;
00373 usage[collision]++;
00374 if (collision > 0 && usage[collision] >= max_usage) {
00375 max_usage = usage[collision];
00376 }
00377 }
00378 printf(
00379 "---\n"
00380 "Hash size: %d\n"
00381 "Nodes used: %d\n"
00382 "Non empty buckets: %d\n"
00383 "Max collision: %d\n",
00384 h->num_buckets, h->size, used_buckets, max_collision
00385 );
00386 printf("{ ");
00387 for (i = 0; i <= max_collision; i++) {
00388 if (usage[i] > 0) {
00389 printf("%d:%d ", i, usage[i]);
00390 #if 0
00391 if (i > 0) {
00392 uint j;
00393
00394 for (j = 0; j < usage[i] * 160 / 800; j++) putchar('#');
00395 }
00396 printf("\n");
00397 #endif
00398 }
00399 }
00400 printf ("}\n");
00401 }
00402 #endif
00403
00404 void clear_Hash(Hash* h, bool free_values)
00405 {
00406 uint i;
00407
00408 #ifdef HASH_STATS
00409 if (h->size > 2000) stat_Hash(h);
00410 #endif
00411
00412
00413 for (i = 0; i < h->num_buckets; i++) {
00414 if (h->buckets_in_use[i]) {
00415 HashNode* node;
00416
00417 h->buckets_in_use[i] = false;
00418
00419 if (free_values) free(h->buckets[i].value);
00420 node = h->buckets[i].next;
00421 while (node != NULL) {
00422 HashNode* prev = node;
00423
00424 node = node->next;
00425 if (free_values) free(prev->value);
00426 free(prev);
00427 }
00428 }
00429 }
00430 h->size = 0;
00431 }
00432
00440 static HashNode* Hash_FindNode(const Hash* h, uint key1, uint key2, HashNode** prev_out)
00441 {
00442 uint hash = h->hash(key1, key2);
00443 HashNode* result = NULL;
00444
00445 #ifdef HASH_DEBUG
00446 debug("Looking for %u, %u", key1, key2);
00447 #endif
00448
00449 if (!h->buckets_in_use[hash]) {
00450 if (prev_out != NULL) *prev_out = NULL;
00451 result = NULL;
00452
00453 } else if (h->buckets[hash].key1 == key1 && h->buckets[hash].key2 == key2) {
00454
00455 result = h->buckets + hash;
00456 if (prev_out != NULL) *prev_out = NULL;
00457 #ifdef HASH_DEBUG
00458 debug("Found in first node: %p", result);
00459 #endif
00460
00461 } else {
00462 HashNode* prev = h->buckets + hash;
00463 HashNode* node;
00464
00465 for (node = prev->next; node != NULL; node = node->next) {
00466 if (node->key1 == key1 && node->key2 == key2) {
00467
00468 result = node;
00469 #ifdef HASH_DEBUG
00470 debug("Found in other node: %p", result);
00471 #endif
00472 break;
00473 }
00474 prev = node;
00475 }
00476 if (prev_out != NULL) *prev_out = prev;
00477 }
00478 #ifdef HASH_DEBUG
00479 if (result == NULL) debug("Not found");
00480 #endif
00481 return result;
00482 }
00483
00484 void* Hash_Delete(Hash* h, uint key1, uint key2)
00485 {
00486 void* result;
00487 HashNode* prev;
00488 HashNode* node = Hash_FindNode(h, key1, key2, &prev);
00489
00490 if (node == NULL) {
00491
00492 result = NULL;
00493 } else if (prev == NULL) {
00494
00495
00496
00497 result = node->value;
00498 if (node->next != NULL) {
00499 HashNode* next = node->next;
00500
00501 *node = *next;
00502
00503 #ifndef NOFREE
00504 free(next);
00505 #endif
00506 } else {
00507
00508
00509 uint hash = h->hash(key1, key2);
00510 h->buckets_in_use[hash] = false;
00511 }
00512 } else {
00513
00514
00515 result = node->value;
00516
00517 prev->next = node->next;
00518
00519 #ifndef NOFREE
00520 free(node);
00521 #endif
00522 }
00523 if (result != NULL) h->size--;
00524 return result;
00525 }
00526
00527
00528 void* Hash_Set(Hash* h, uint key1, uint key2, void* value)
00529 {
00530 HashNode* prev;
00531 HashNode* node = Hash_FindNode(h, key1, key2, &prev);
00532
00533 if (node != NULL) {
00534
00535 void* result = node->value;
00536
00537 node->value = value;
00538 return result;
00539 }
00540
00541 if (prev == NULL) {
00542
00543 uint hash = h->hash(key1, key2);
00544 h->buckets_in_use[hash] = true;
00545 node = h->buckets + hash;
00546 } else {
00547
00548 node = MallocT<HashNode>(1);
00549 prev->next = node;
00550 }
00551 node->next = NULL;
00552 node->key1 = key1;
00553 node->key2 = key2;
00554 node->value = value;
00555 h->size++;
00556 return NULL;
00557 }
00558
00559 void* Hash_Get(const Hash* h, uint key1, uint key2)
00560 {
00561 HashNode* node = Hash_FindNode(h, key1, key2, NULL);
00562
00563 #ifdef HASH_DEBUG
00564 debug("Found node: %p", node);
00565 #endif
00566 return (node != NULL) ? node->value : NULL;
00567 }
00568
00569 uint Hash_Size(const Hash* h)
00570 {
00571 return h->size;
00572 }