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