00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <errno.h>
00004
00005 #include "splay.h"
00006
00007 cp_splaynode *cp_splaynode_create(void *key, void *value, cp_mempool *pool)
00008 {
00009 cp_splaynode *node;
00010 if (pool)
00011 node = cp_mempool_calloc(pool);
00012 else
00013 node = calloc(1, sizeof(cp_splaynode));
00014 if (node == NULL) return NULL;
00015
00016 node->key = key;
00017 node->value = value;
00018
00019 return node;
00020 }
00021
00022 void cp_splaytree_destroy_node(cp_splaytree *tree, cp_splaynode *node)
00023 {
00024 if (node)
00025 {
00026 if ((tree->mode & COLLECTION_MODE_DEEP))
00027 {
00028 if (tree->key_dtr) (*tree->key_dtr)(node->key);
00029 if ((tree->mode & COLLECTION_MODE_MULTIPLE_VALUES) && node->value)
00030 cp_vector_destroy_custom(node->value, tree->value_dtr);
00031 else if (tree->value_dtr)
00032 (*tree->value_dtr)(node->value);
00033 }
00034 else if ((tree->mode & COLLECTION_MODE_MULTIPLE_VALUES) && node->value)
00035 cp_vector_destroy(node->value);
00036 if (tree->mempool)
00037 cp_mempool_free(tree->mempool, node);
00038 else
00039 free(node);
00040 }
00041 }
00042
00043 void cp_splaytree_destroy_node_deep(cp_splaytree *tree, cp_splaynode *node)
00044 {
00045 if (node)
00046 {
00047 cp_splaynode *parent;
00048 cp_splaynode *child;
00049
00050 parent = node;
00051 while (node)
00052 {
00053 if (node->right && node->right != parent)
00054 {
00055 child = node->right;
00056 node->right = parent;
00057 parent = node;
00058 node = child;
00059 }
00060 else if (node->left && node->left != parent)
00061 {
00062 child = node->left;
00063 node->left = node->right;
00064 node->right = parent;
00065 parent = node;
00066 node = child;
00067 }
00068 else
00069 {
00070 cp_splaytree_destroy_node(tree, node);
00071 if (node != parent)
00072 {
00073 node = parent;
00074 parent = node->right;
00075 }
00076 else
00077 break;
00078 }
00079 }
00080 }
00081 }
00082
00083 cp_splaytree *cp_splaytree_create(cp_compare_fn cmp)
00084 {
00085 cp_splaytree *tree = calloc(1, sizeof(cp_splaytree));
00086 if (tree == NULL) return NULL;
00087
00088 tree->cmp = cmp;
00089 tree->mode = COLLECTION_MODE_NOSYNC;
00090
00091 return tree;
00092 }
00093
00094
00095
00096
00097 cp_splaytree *
00098 cp_splaytree_create_by_option(int mode,
00099 cp_compare_fn cmp,
00100 cp_copy_fn key_copy,
00101 cp_destructor_fn key_dtr,
00102 cp_copy_fn val_copy,
00103 cp_destructor_fn val_dtr)
00104 {
00105 cp_splaytree *tree = cp_splaytree_create(cmp);
00106 if (tree == NULL) return NULL;
00107
00108 tree->mode = mode;
00109 tree->key_copy = key_copy;
00110 tree->key_dtr = key_dtr;
00111 tree->value_copy = val_copy;
00112 tree->value_dtr = val_dtr;
00113
00114 if (!(mode & COLLECTION_MODE_NOSYNC))
00115 {
00116 tree->lock = malloc(sizeof(cp_lock));
00117 if (tree->lock == NULL)
00118 {
00119 cp_splaytree_destroy(tree);
00120 return NULL;
00121 }
00122 if (cp_lock_init(tree->lock, NULL) != 0)
00123 {
00124 cp_splaytree_destroy(tree);
00125 return NULL;
00126 }
00127 }
00128
00129 return tree;
00130 }
00131
00132 void cp_splaytree_destroy(cp_splaytree *tree)
00133 {
00134 if (tree)
00135 {
00136 cp_splaytree_destroy_node_deep(tree, tree->root);
00137 if (tree->lock)
00138 {
00139 cp_lock_destroy(tree->lock);
00140 free(tree->lock);
00141 }
00142 free(tree);
00143 }
00144 }
00145
00146 void cp_splaytree_destroy_custom(cp_splaytree *tree,
00147 cp_destructor_fn key_dtr,
00148 cp_destructor_fn val_dtr)
00149 {
00150 tree->mode |= COLLECTION_MODE_DEEP;
00151 tree->key_dtr = key_dtr;
00152 tree->value_dtr = val_dtr;
00153 cp_splaytree_destroy(tree);
00154 }
00155
00156 static int cp_splaytree_lock_internal(cp_splaytree *tree, int type)
00157 {
00158 int rc;
00159
00160 switch (type)
00161 {
00162 case COLLECTION_LOCK_READ:
00163 rc = cp_lock_rdlock(tree->lock);
00164 break;
00165
00166 case COLLECTION_LOCK_WRITE:
00167 rc = cp_lock_wrlock(tree->lock);
00168 break;
00169
00170 case COLLECTION_LOCK_NONE:
00171 rc = 0;
00172 break;
00173
00174 default:
00175 rc = EINVAL;
00176 break;
00177 }
00178
00179
00180 if (rc) errno = rc;
00181
00182 return rc;
00183 }
00184
00185 static int cp_splaytree_unlock_internal(cp_splaytree *tree)
00186 {
00187 return cp_lock_unlock(tree->lock);
00188 }
00189
00190 int cp_splaytree_txlock(cp_splaytree *tree, int type)
00191 {
00192
00193 errno = 0;
00194
00195 if (tree->mode & COLLECTION_MODE_NOSYNC) return 0;
00196 if (tree->mode & COLLECTION_MODE_IN_TRANSACTION &&
00197 tree->txtype == COLLECTION_LOCK_WRITE)
00198 {
00199 cp_thread self = cp_thread_self();
00200 if (cp_thread_equal(self, tree->txowner)) return 0;
00201 }
00202 return cp_splaytree_lock_internal(tree, type);
00203 }
00204
00205 int cp_splaytree_txunlock(cp_splaytree *tree)
00206 {
00207 if (tree->mode & COLLECTION_MODE_NOSYNC) return 0;
00208 if (tree->mode & COLLECTION_MODE_IN_TRANSACTION &&
00209 tree->txtype == COLLECTION_LOCK_WRITE)
00210 {
00211 cp_thread self = cp_thread_self();
00212 if (cp_thread_equal(self, tree->txowner)) return 0;
00213 }
00214 return cp_splaytree_unlock_internal(tree);
00215 }
00216
00217
00218 int cp_splaytree_lock(cp_splaytree *tree, int type)
00219 {
00220 int rc;
00221 if ((tree->mode & COLLECTION_MODE_NOSYNC)) return EINVAL;
00222 if ((rc = cp_splaytree_lock_internal(tree, type))) return rc;
00223 tree->txtype = type;
00224 tree->txowner = cp_thread_self();
00225 tree->mode |= COLLECTION_MODE_IN_TRANSACTION;
00226 return 0;
00227 }
00228
00229
00230 int cp_splaytree_unlock(cp_splaytree *tree)
00231 {
00232 cp_thread self = cp_thread_self();
00233 if (tree->txowner == self)
00234 {
00235 tree->txowner = 0;
00236 tree->txtype = 0;
00237 tree->mode ^= COLLECTION_MODE_IN_TRANSACTION;
00238 }
00239 else if (tree->txtype == COLLECTION_LOCK_WRITE)
00240 return -1;
00241 return cp_splaytree_unlock_internal(tree);
00242 }
00243
00244
00245 int cp_splaytree_set_mode(cp_splaytree *tree, int mode)
00246 {
00247 int rc;
00248 int nosync;
00249
00250
00251 if ((tree->mode & COLLECTION_MODE_IN_TRANSACTION) &&
00252 (mode & COLLECTION_MODE_NOSYNC)) return EINVAL;
00253
00254 if ((mode & COLLECTION_MODE_MULTIPLE_VALUES)) return EINVAL;
00255
00256 if ((rc = cp_splaytree_txlock(tree, COLLECTION_LOCK_WRITE))) return rc;
00257
00258 nosync = tree->mode & COLLECTION_MODE_NOSYNC;
00259
00260 tree->mode |= mode;
00261
00262 if (!nosync)
00263 cp_splaytree_txunlock(tree);
00264
00265 return 0;
00266 }
00267
00268
00269
00270
00271
00272 int cp_splaytree_unset_mode(cp_splaytree *tree, int mode)
00273 {
00274 int rc;
00275 int nosync;
00276
00277
00278 if ((mode & COLLECTION_MODE_MULTIPLE_VALUES)) return EINVAL;
00279
00280 if ((rc = cp_splaytree_txlock(tree, COLLECTION_LOCK_WRITE))) return rc;
00281
00282 nosync = tree->mode & COLLECTION_MODE_NOSYNC;
00283
00284
00285 if ((mode & COLLECTION_MODE_NOSYNC) && tree->lock == NULL)
00286 {
00287
00288 if ((tree->lock = malloc(sizeof(cp_lock))) == NULL)
00289 return -1;
00290 if (cp_lock_init(tree->lock, NULL))
00291 return -1;
00292 }
00293
00294
00295 tree->mode &= tree->mode ^ mode;
00296 if (!nosync)
00297 cp_splaytree_txunlock(tree);
00298
00299 return 0;
00300 }
00301
00302 int cp_splaytree_get_mode(cp_splaytree *tree)
00303 {
00304 return tree->mode;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 void right_rotate(cp_splaynode **node)
00318 {
00319 cp_splaynode *p = *node;
00320 cp_splaynode *q = p->left;
00321 p->left = q->right;
00322 q->right = p;
00323 *node = q;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 void left_rotate(cp_splaynode **node)
00336 {
00337 cp_splaynode *p = *node;
00338 cp_splaynode *q = p->right;
00339
00340 p->right = q->left;
00341 q->left = p;
00342 *node = q;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 static void left_right_rotate(cp_splaynode **node)
00357 {
00358 cp_splaynode *p = *node;
00359 cp_splaynode *q = (*node)->left;
00360 cp_splaynode *r = q->right;
00361
00362 q->right = r->left;
00363 p->left = r->right;
00364 r->right = p;
00365 r->left = q;
00366
00367 *node = r;
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 static void right_left_rotate(cp_splaynode **node)
00382 {
00383 cp_splaynode *p = *node;
00384 cp_splaynode *q = (*node)->right;
00385 cp_splaynode *r = q->left;
00386
00387 q->left = r->right;
00388 p->right = r->left;
00389 r->left = p;
00390 r->right = q;
00391
00392 *node = r;
00393 }
00394
00395
00396 static cp_splaynode *
00397 create_splaynode(cp_splaytree *tree, void *key, void *value)
00398 {
00399 cp_splaynode *node = NULL;
00400
00401 if (tree->mode & COLLECTION_MODE_COPY)
00402 {
00403 void *k = tree->key_copy ? (*tree->key_copy)(key) : key;
00404 if (k)
00405 {
00406 void *v = tree->value_copy ? (*tree->value_copy)(value) : value;
00407 if (v)
00408 node = cp_splaynode_create(k, v, tree->mempool);
00409 }
00410 }
00411 else
00412 node = cp_splaynode_create(key, value, tree->mempool);
00413
00414 if (node && (tree->mode & COLLECTION_MODE_MULTIPLE_VALUES))
00415 {
00416 cp_vector *m = cp_vector_create(1);
00417 if (m == NULL)
00418 {
00419 cp_splaytree_destroy_node(tree, node);
00420 return NULL;
00421 }
00422
00423 cp_vector_add_element(m, node->value);
00424 node->value = m;
00425 }
00426
00427 return node;
00428 }
00429
00430
00431
00432
00433 static void *
00434 update_splaynode(cp_splaytree *tree,
00435 cp_splaynode *node,
00436 void *key, void *value)
00437 {
00438 void *new_key = key;
00439 void *new_value = value;
00440
00441 if (tree->mode & COLLECTION_MODE_COPY)
00442 {
00443 if (tree->key_copy)
00444 {
00445 new_key = (*tree->key_copy)(key);
00446 if (new_key == NULL) return NULL;
00447 }
00448 if (tree->value_copy)
00449 {
00450 new_value = (*tree->value_copy)(value);
00451 if (new_value == NULL) return NULL;
00452 }
00453 }
00454
00455 if (tree->mode & COLLECTION_MODE_DEEP)
00456 {
00457 if (tree->key_dtr)
00458 (*tree->key_dtr)(node->key);
00459 if (tree->value_dtr && !(tree->mode & COLLECTION_MODE_MULTIPLE_VALUES))
00460 (*tree->value_dtr)(node->value);
00461 }
00462
00463 node->key = new_key;
00464 if ((tree->mode & COLLECTION_MODE_MULTIPLE_VALUES))
00465 {
00466 cp_vector_add_element(node->value, new_value);
00467 return node->value;
00468 }
00469 else
00470 node->value = new_value;
00471
00472 return new_value;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 static void desplay(cp_splaynode **node, int *splay_factor, int op)
00484 {
00485 switch (*splay_factor)
00486 {
00487 case 0:
00488 *splay_factor += op;
00489 break;
00490
00491 case -1:
00492 if (op == 0)
00493 right_rotate(node);
00494 else
00495 {
00496 if (op == -1)
00497 {
00498 right_rotate(node);
00499 right_rotate(node);
00500 }
00501 else
00502 right_left_rotate(node);
00503 *splay_factor = 0;
00504 }
00505 break;
00506
00507 case 1:
00508 if (op == 0)
00509 left_rotate(node);
00510 else
00511 {
00512 if (op == 1)
00513 {
00514 left_rotate(node);
00515 left_rotate(node);
00516 }
00517 else
00518 left_right_rotate(node);
00519 *splay_factor = 0;
00520 }
00521 break;
00522 }
00523 }
00524
00525 static void *
00526 splay_insert(cp_splaytree *tree,
00527 cp_splaynode **node,
00528 void *key, void *value,
00529 int *splay_factor)
00530 {
00531 int cmp;
00532 void *res;
00533
00534 if (*node == NULL)
00535 {
00536 *node = create_splaynode(tree, key, value);
00537 if (*node)
00538 {
00539 tree->items++;
00540 return (*node)->value;
00541 }
00542 return NULL;
00543 }
00544
00545 res = (*node)->value;
00546
00547 cmp = tree->cmp((*node)->key, key);
00548 if (cmp == 0)
00549 {
00550 *splay_factor = 0;
00551 return update_splaynode(tree, *node, key, value);
00552 }
00553 else if (cmp > 0)
00554 {
00555 res = splay_insert(tree, &(*node)->left, key, value, splay_factor);
00556 desplay(node, splay_factor, -1);
00557 }
00558 else
00559 {
00560 res = splay_insert(tree, &(*node)->right, key, value, splay_factor);
00561 desplay(node, splay_factor, 1);
00562 }
00563
00564 return res;
00565 }
00566
00567 void *cp_splaytree_insert(cp_splaytree *tree, void *key, void *value)
00568 {
00569 void *res;
00570 int splay_factor = 0;
00571
00572
00573 if (cp_splaytree_txlock(tree, COLLECTION_LOCK_WRITE)) return NULL;
00574
00575 res = splay_insert(tree, &tree->root, key, value, &splay_factor);
00576 desplay(&tree->root, &splay_factor, 0);
00577
00578
00579 cp_splaytree_txunlock(tree);
00580
00581 return res;
00582 }
00583
00584 static void *
00585 splay_get(cp_splaytree *tree,
00586 cp_splaynode **node,
00587 void *key,
00588 int *splay_factor)
00589 {
00590 int cmp;
00591 void *res;
00592
00593 if (*node == NULL) return NULL;
00594
00595 cmp = tree->cmp((*node)->key, key);
00596 if (cmp == 0)
00597 {
00598 *splay_factor = 0;
00599 res = (*node)->value;
00600 }
00601 else if (cmp > 0)
00602 {
00603 if ((res = splay_get(tree, &(*node)->left, key, splay_factor)))
00604 desplay(node, splay_factor, -1);
00605 }
00606 else
00607 {
00608 if ((res = splay_get(tree, &(*node)->right, key, splay_factor)))
00609 desplay(node, splay_factor, 1);
00610 }
00611
00612 return res;
00613 }
00614
00615 void *cp_splaytree_get(cp_splaytree *tree, void *key)
00616 {
00617 int splay_factor = 0;
00618 cp_splaynode **node = &tree->root;
00619 void *res = NULL;
00620
00621
00622
00623
00624
00625
00626 if (cp_splaytree_txlock(tree, COLLECTION_LOCK_WRITE)) return NULL;
00627
00628 res = splay_get(tree, node, key, &splay_factor);
00629 desplay(node, &splay_factor, 0);
00630
00631
00632 cp_splaytree_txunlock(tree);
00633
00634 return res;
00635 }
00636
00637 static void *
00638 splaytree_find_internal(cp_splaytree *tree,
00639 cp_splaynode *curr,
00640 void *key,
00641 cp_op op)
00642 {
00643 void *res = NULL;
00644
00645 if (curr)
00646 {
00647 int cmp = tree->cmp(key, curr->key);
00648 if (cmp == 0)
00649 {
00650 if (op == CP_OP_NE)
00651 {
00652 if (curr->right) return curr->right->value;
00653 if (curr->left) return curr->left->value;
00654 }
00655
00656 if (op == CP_OP_GT)
00657 {
00658 if (curr->right)
00659 {
00660 curr = curr->right;
00661 while (curr->left) curr = curr->left;
00662 }
00663 else
00664 return NULL;
00665 }
00666
00667 if (op == CP_OP_LT)
00668 {
00669 if (curr->left)
00670 {
00671 curr = curr->left;
00672 while (curr->right) curr = curr->right;
00673 }
00674 else
00675 return NULL;
00676 }
00677
00678 return curr->value;
00679 }
00680 else
00681 {
00682 if (op == CP_OP_NE) return curr->value;
00683 if (cmp > 0)
00684 res = splaytree_find_internal(tree, curr->right, key, op);
00685 else
00686 res = splaytree_find_internal(tree, curr->left, key, op);
00687
00688 if (res == NULL)
00689 {
00690 if ((cmp > 0 && (op == CP_OP_LT || op == CP_OP_LE)) ||
00691 (cmp < 0 && (op == CP_OP_GE || op == CP_OP_GT)))
00692 res = curr->value;
00693 }
00694 }
00695 }
00696
00697 return res;
00698 }
00699
00700 void *cp_splaytree_find(cp_splaytree *tree, void *key, cp_op op)
00701 {
00702 void *res = NULL;
00703 if (op == CP_OP_EQ) return cp_splaytree_get(tree, key);
00704
00705
00706 if (cp_splaytree_txlock(tree, COLLECTION_LOCK_READ)) return NULL;
00707
00708 res = splaytree_find_internal(tree, tree->root, key, op);
00709
00710
00711 cp_splaytree_txunlock(tree);
00712
00713 return res;
00714 }
00715
00716 int cp_splaytree_contains(cp_splaytree *tree, void *key)
00717 {
00718 return (cp_splaytree_get(tree, key) != NULL);
00719 }
00720
00721
00722 static void swap_node_content(cp_splaynode *a, cp_splaynode *b)
00723 {
00724 void *tmpkey, *tmpval;
00725
00726 tmpkey = a->key;
00727 a->key = b->key;
00728 b->key = tmpkey;
00729
00730 tmpval = a->value;
00731 a->value = b->value;
00732 b->value = tmpval;
00733 }
00734
00735 static void *
00736 splay_delete(cp_splaytree *tree,
00737 cp_splaynode **node,
00738 void *key,
00739 int *splay_factor)
00740 {
00741 void *res;
00742 int cmp;
00743
00744 if ((*node) == NULL)
00745 {
00746 *splay_factor = 0;
00747 return NULL;
00748 }
00749
00750 cmp = (*tree->cmp)((*node)->key, key);
00751 if (cmp == 0)
00752 {
00753 cp_splaynode *x;
00754 res = (*node)->value;
00755 tree->items--;
00756
00757 if ((*node)->right && (*node)->left)
00758 {
00759 cp_splaynode *surrogate = *node;
00760 node = &(*node)->right;
00761 while ((*node)->left) node = &(*node)->left;
00762 swap_node_content(*node, surrogate);
00763 }
00764
00765 x = *node;
00766 if ((*node)->right)
00767 *node = (*node)->right;
00768 else
00769 *node = (*node)->left;
00770 cp_splaytree_destroy_node(tree, x);
00771
00772 *splay_factor = 0;
00773 }
00774 else if (cmp > 0)
00775 {
00776 res = splay_delete(tree, &(*node)->left, key, splay_factor);
00777 desplay(node, splay_factor, -1);
00778 }
00779 else
00780 {
00781 res = splay_delete(tree, &(*node)->right, key, splay_factor);
00782 desplay(node, splay_factor, 1);
00783 }
00784
00785 return res;
00786 }
00787
00788 void *cp_splaytree_delete(cp_splaytree *tree, void *key)
00789 {
00790 void *res = NULL;
00791 int splay_factor = 0;
00792 cp_splaynode **node;
00793
00794 if (cp_splaytree_txlock(tree, COLLECTION_LOCK_WRITE)) return NULL;
00795
00796 node = &tree->root;
00797
00798 res = splay_delete(tree, node, key, &splay_factor);
00799 desplay(node, &splay_factor, 0);
00800
00801 cp_splaytree_txunlock(tree);
00802
00803 return res;
00804 }
00805
00806
00807 static int
00808 splay_scan_pre_order(cp_splaynode *node,
00809 cp_callback_fn callback,
00810 void *prm)
00811 {
00812 int rc;
00813
00814 if (node)
00815 {
00816 if ((rc = (*callback)(node, prm))) return rc;
00817 if ((rc = splay_scan_pre_order(node->right, callback, prm))) return rc;
00818 if ((rc = splay_scan_pre_order(node->left, callback, prm))) return rc;
00819 }
00820
00821 return 0;
00822 }
00823
00824 int cp_splaytree_callback_preorder(cp_splaytree *tree,
00825 cp_callback_fn callback,
00826 void *prm)
00827 {
00828 int rc;
00829
00830 if ((rc = cp_splaytree_txlock(tree, COLLECTION_LOCK_READ))) return rc;
00831 rc = splay_scan_pre_order(tree->root, callback, prm);
00832 cp_splaytree_txunlock(tree);
00833
00834 return rc;
00835 }
00836
00837 static int
00838 splay_scan_in_order(cp_splaynode *node, cp_callback_fn callback, void *prm)
00839 {
00840 int rc;
00841
00842 if (node)
00843 {
00844 if ((rc = splay_scan_in_order(node->right, callback, prm))) return rc;
00845 if ((rc = (*callback)(node, prm))) return rc;
00846 if ((rc = splay_scan_in_order(node->left, callback, prm))) return rc;
00847 }
00848
00849 return 0;
00850 }
00851
00852 int cp_splaytree_callback(cp_splaytree *tree,
00853 cp_callback_fn callback,
00854 void *prm)
00855 {
00856 int rc;
00857
00858 if ((rc = cp_splaytree_txlock(tree, COLLECTION_LOCK_READ))) return rc;
00859 rc = splay_scan_in_order(tree->root, callback, prm);
00860 cp_splaytree_txunlock(tree);
00861
00862 return rc;
00863 }
00864
00865 static int
00866 splay_scan_post_order(cp_splaynode *node,
00867 cp_callback_fn callback,
00868 void *prm)
00869 {
00870 int rc;
00871
00872 if (node)
00873 {
00874 if ((rc = splay_scan_post_order(node->right, callback, prm))) return rc;
00875 if ((rc = splay_scan_post_order(node->left, callback, prm))) return rc;
00876 if ((rc = (*callback)(node, prm))) return rc;
00877 }
00878
00879 return 0;
00880 }
00881
00882 int cp_splaytree_callback_postorder(cp_splaytree *tree,
00883 cp_callback_fn callback,
00884 void *prm)
00885 {
00886 int rc;
00887
00888 if ((rc = cp_splaytree_txlock(tree, COLLECTION_LOCK_READ))) return rc;
00889 rc = splay_scan_post_order(tree->root, callback, prm);
00890 cp_splaytree_txunlock(tree);
00891
00892 return rc;
00893 }
00894
00895 int cp_splaytree_count(cp_splaytree *tree)
00896 {
00897 return tree->items;
00898 }
00899
00900
00901 void cp_splaynode_print(cp_splaynode *node, int level)
00902 {
00903 int i;
00904 if (node->right) cp_splaynode_print(node->right, level + 1);
00905 for (i = 0; i < level; i++) printf(" . ");
00906 printf("[%s => %s]\n", (char *) node->key, (char *) node->value);
00907 if (node->left) cp_splaynode_print(node->left, level + 1);
00908 }
00909
00910 void cp_splaynode_multi_print(cp_splaynode *node, int level)
00911 {
00912 int i;
00913 cp_vector *v = node->value;
00914 if (node->right) cp_splaynode_multi_print(node->right, level + 1);
00915
00916 for (i = 0; i < level; i++) printf(" . ");
00917 printf("[%s => ", (char *) node->key);
00918
00919 for (i = 0; i < cp_vector_size(v); i++)
00920 printf("%s; ", (char *) cp_vector_element_at(v, i));
00921
00922 printf("]\n");
00923
00924 if (node->left) cp_splaynode_multi_print(node->left, level + 1);
00925 }
00926
00927 void cp_splaytree_dump(cp_splaytree *tree)
00928 {
00929 if (tree->root)
00930 {
00931 if ((tree->mode & COLLECTION_MODE_MULTIPLE_VALUES))
00932 cp_splaynode_multi_print(tree->root, 0);
00933 else
00934 cp_splaynode_print(tree->root, 0);
00935 }
00936 }
00937
00938
00939 int cp_splaytree_use_mempool(cp_splaytree *tree, cp_mempool *pool)
00940 {
00941 int rc = 0;
00942
00943 if ((rc = cp_splaytree_txlock(tree, COLLECTION_LOCK_WRITE))) return rc;
00944
00945 if (pool)
00946 {
00947 if (pool->item_size < sizeof(cp_splaynode))
00948 {
00949 rc = EINVAL;
00950 goto DONE;
00951 }
00952 if (tree->mempool)
00953 {
00954 if (tree->items)
00955 {
00956 rc = ENOTEMPTY;
00957 goto DONE;
00958 }
00959 cp_mempool_destroy(tree->mempool);
00960 }
00961 cp_mempool_inc_refcount(pool);
00962 tree->mempool = pool;
00963 }
00964 else
00965 {
00966 tree->mempool =
00967 cp_mempool_create_by_option(COLLECTION_MODE_NOSYNC,
00968 sizeof(cp_splaynode), 0);
00969 if (tree->mempool == NULL)
00970 {
00971 rc = ENOMEM;
00972 goto DONE;
00973 }
00974 }
00975
00976 DONE:
00977 cp_splaytree_txunlock(tree);
00978 return rc;
00979 }
00980
00981
00982
00983 int cp_splaytree_share_mempool(cp_splaytree *tree, cp_shared_mempool *pool)
00984 {
00985 int rc;
00986
00987 if ((rc = cp_splaytree_txlock(tree, COLLECTION_LOCK_WRITE))) return rc;
00988
00989 if (tree->mempool)
00990 {
00991 if (tree->items)
00992 {
00993 rc = ENOTEMPTY;
00994 goto DONE;
00995 }
00996
00997 cp_mempool_destroy(tree->mempool);
00998 }
00999
01000 tree->mempool = cp_shared_mempool_register(pool, sizeof(cp_splaynode));
01001 if (tree->mempool == NULL)
01002 {
01003 rc = ENOMEM;
01004 goto DONE;
01005 }
01006
01007 DONE:
01008 cp_splaytree_txunlock(tree);
01009 return rc;
01010 }
01011