void sl_add_index(Skiplist *sl, SkiplistComparator comp, SkiplistComparator compk) { struct skiplistnode *m; Skiplist *ni; int icount=0; Alarm(SKIPLIST, "Adding index to %p\n", sl); sl_find(sl->index, (void *)comp, &m); if(m) return; /* Index already there! */ ni = (Skiplist *)malloc(sizeof(Skiplist)); sli_init(ni); sl_set_compare(ni, comp, compk); /* Build the new index... This can be expensive! */ m = sl_insert(sl->index, ni); while(m->prev) m=m->prev, icount++; for(m=sl_getlist(sl); m; sl_next(sl, &m)) { int j=icount-1; struct skiplistnode *nsln; nsln = sl_insert(ni, m->data); /* skip from main index down list */ while(j>0) m=m->nextindex, j--; /* insert this node in the indexlist after m */ nsln->nextindex = m->nextindex; if(m->nextindex) m->nextindex->previndex = nsln; nsln->previndex = m; m->nextindex = nsln; } }
static char *sl_test_update(void) { int v1 = 5; int v2 = 6; int *v; sl *slist = sl_create(); sl_insert(slist, 9, &v1); sl_insert(slist, 9, &v2); v = sl_find(slist, 9); mu_assert("updating list with one element fails", *v == v2); sl_destroy(slist); return 0; }
int main() { srand((int)time(NULL)); skiplist* S = (skiplist*)malloc(sizeof(skiplist)); node nodes[2] = { {-1, &nodes[1], NULL}, {1000000, NULL, NULL} }; S->top = &nodes[0]; int i; printf("Start...\n"); scanf("%d", &i); while (i != -1) { if (i == -2) { sl_print(S); } else { sl_insert(S, i); } scanf("%d", &i); } delete(S); printf("End of program!\n"); return 0; }
vio_err_t vio_partition_val(vio_ctx *ctx, vio_val *v, vio_val *q, vio_val **out_rets, vio_val **out_parts) { vio_err_t err = 0; struct partition *p = NULL; struct partition_item *it = NULL; vio_val *ret; sl_skiplist parts; sl_init(&parts, cmp_vals, ctx, NULL, NULL); for (uint32_t i = 0; i < v->vlen; ++i) { VIO__ERRIF(ctx->sp >= VIO_STACK_SIZE, VE_STACK_OVERFLOW); ctx->stack[ctx->sp++] = v->vv[i]; vio_exec(ctx, q->bc); ret = ctx->stack[--ctx->sp]; if (!sl_find(&parts, ret, &p)) { VIO__ERRIF((p = (struct partition *)malloc(sizeof(struct partition))) == NULL, VE_ALLOC_FAIL); p->last = NULL; p->size = 0; sl_insert(&parts, ret, p, NULL); } VIO__ERRIF((it = (struct partition_item *)malloc(sizeof(struct partition_item))) == NULL, VE_ALLOC_FAIL); it->next = p->last; it->v = v->vv[i]; p->last = it; ++p->size; } VIO__CHECK(vio_vec(ctx, out_rets, sl_size(&parts), NULL)); VIO__CHECK(vio_vec(ctx, out_parts, sl_size(&parts), NULL)); struct part_data pd = { .i = 0, .rets = *out_rets, .parts = *out_parts, .ctx = ctx }; sl_iter(&parts, fill_partitions_and_free, &pd); sl_free(&parts); return 0; error: sl_iter(&parts, gotta_free_em_all, NULL); sl_free(&parts); return err; } vio_err_t vio_partition(vio_ctx *ctx) { vio_err_t err = 0; vio_val *q, *vec, *rets, *parts; VIO__RAISEIF(ctx->sp < 2, VE_STACK_EMPTY, "Partition context requires a quotation and vector, but the " "stack doesnt't have enough values."); VIO__CHECK(vio_coerce(ctx, ctx->stack[--ctx->sp], &q, vv_quot)); VIO__CHECK(vio_coerce(ctx, ctx->stack[--ctx->sp], &vec, vv_vec)); VIO__CHECK(vio_partition_val(ctx, vec, q, &rets, &parts)); ctx->stack[ctx->sp++] = rets; ctx->stack[ctx->sp++] = parts; return 0; error: return err; }
struct skiplistnode *sl_append(Skiplist *sl, void *data) { int nh=1, ch, compared; struct skiplistnode *lastnode, *nodeago; if(sl->bottomend != sl->bottom) { compared=sl->compare(data, sl->bottomend->prev->data); /* If it doesn't belong at the end, then fail */ if(compared<=0) return NULL; } if(sl->preheight) { while(nh < sl->preheight && get_b_rand()) nh++; } else { while(nh <= sl->height && get_b_rand()) nh++; } /* Now we have the new hieght at which we wish to insert our new node */ /* Let us make sure that our tree is a least that tall (grow if necessary)*/ lastnode = sl->bottomend; nodeago = NULL; if(!lastnode) return sl_insert(sl, data); for(;sl->height<nh;sl->height++) { assert(sl->top); sl->top->up = (struct skiplistnode *)malloc(sizeof(struct skiplistnode)); sl->top->up->down = sl->top; sl->top = sl->topend = sl->top->up; sl->top->prev = sl->top->next = sl->top->nextindex = sl->top->previndex = NULL; sl->top->data = NULL; sl->top->sl = sl; } ch = sl->height; while(nh) { struct skiplistnode *anode; anode = (struct skiplistnode *)malloc(sizeof(struct skiplistnode)); anode->next = lastnode; anode->prev = lastnode->prev; anode->up = NULL; anode->down = nodeago; /* If this the bottom, we are appending, so bottomend should change */ if(!nodeago) sl->bottomend = anode; if(lastnode->prev) { if(lastnode == sl->bottom) sl->bottom = anode; else if (lastnode == sl->top) sl->top = anode; } nodeago = anode; lastnode = lastnode->up; nh--; } sl->size++; return(nodeago); }
/* Apply a merge of the two sorted lists */ struct sl* sl_join(struct sl *l1, struct sl *l2) { struct sl *joined = sl_init(); sl_cursor cur1 = l1->lists[0].head->next; sl_cursor cur2 = l2->lists[0].head->next; while(cur1->next && cur2->next) { if(G_DATA_GREATER(cur1->data, cur2->data)) { sl_insert(joined, cur1->data); cur1 = cur1->next; } else { sl_insert(joined, cur2->data); cur2 = cur2->next; } } while(cur1->next) { sl_insert(joined, cur1->data); cur1 = cur1->next; } while(cur2->next) { sl_insert(joined, cur2->data); cur2 = cur2->next; } return joined; }
void test_sl_join(CuTest* tc) { char* s1; sl* s = sl_new(4); sl_append(s, "123"); sl_appendf(s, "%1$s%1$s", "testing"); addsome(s, "%i", 456); sl_insert(s, 1, "inserted"); sl_insertf(s, 2, "%s%s", "ins", "ertedf"); s1 = sl_join(s, ""); CuAssertStrEquals(tc, "123insertedinsertedftestingtesting456", s1); free(s1); s1 = sl_join(s, "--"); CuAssertStrEquals(tc, "123--inserted--insertedf--testingtesting--456", s1); free(s1); s1 = sl_join_reverse(s, "--"); CuAssertStrEquals(tc, "456--testingtesting--insertedf--inserted--123", s1); free(s1); sl_free2(s); }
void test_setup(void) { srand(time(NULL)); slist = sl_create(); klist = kl_create(); for(int i = 0; i < ARRAY_LEN(keys); i++) { sl_insert(slist, keys[i], &vals[i]); } sl_output(slist); printf("\n"); for(int i = 0; i < ARRAY_LEN(keys); i++) { kl_insert(klist, keys[i], &vals[i]); } kl_output(klist); printf("\n"); }
static LocatorNode_t *locator_new_node (LocatorKind_t kind, const unsigned char *addr, uint32_t port) { LocSearchData data; LocatorNode_t **npp, *np; int is_new; data.kind = kind; data.addr = addr; data.port = port; npp = sl_insert (&loc_list, &data, &is_new, loc_cmp); if (!npp) { warn_printf ("locator_new_node: not enough memory for node!"); return (NULL); } if (is_new) { np = mds_pool_alloc (&mem_blocks [MB_LOCATOR]); if (!np) { warn_printf ("locator_new_node: not enough memory for locator data!"); #ifdef LIST_DELETE_NODE sl_delete_node (&loc_list, npp); #else sl_delete (&loc_list, &data, loc_cmp); #endif return (NULL); } np->users = 1; np->locator.kind = kind; np->locator.port = port; memcpy (np->locator.address, addr, sizeof (np->locator.address)); memset (&np->locator.scope_id, 0, 8); *npp = np; } else { np = *npp; np->users++; } return (np); }
Skiplist *sl_concat(Skiplist *sl1, Skiplist *sl2) { /* Check integrity! */ Skiplist temp; struct skiplistnode *b2; if(sl1->bottomend == NULL || sl1->bottomend->prev == NULL) { sl_remove_all(sl1, free); temp = *sl1; *sl1 = *sl2; *sl2 = temp; /* swap them so that sl2 can be freed normally upon return. */ return sl1; } if(sl2->bottom == NULL || sl2->bottom->next == NULL) { sl_remove_all(sl2, free); return sl1; } b2 = sl_getlist(sl2); while(b2) { sl_insert(sl1, b2->data); sl_next(sl2, &b2); } sl_remove_all(sl2, NULL); return sl1; }
struct skiplistnode *sl_append(Skiplist *sl, void *data) { return sl_insert(sl, data); }
struct skiplistnode *sl_insert_compare(Skiplist *sl, void *data, SkiplistComparator comp) { struct skiplistnode *m, *p, *tmp, *ret, **stack; int nh=1, ch, stacki; ret = NULL; /*sl_print_struct(sl, "BI: ");*/ if(!sl->top) { sl->height = 1; sl->topend = sl->bottomend = sl->top = sl->bottom = (struct skiplistnode *)malloc(sizeof(struct skiplistnode)); assert(sl->top); sl->top->next = sl->top->data = sl->top->prev = sl->top->up = sl->top->down = sl->top->nextindex = sl->top->previndex = NULL; sl->top->sl = sl; } if(sl->preheight) { while(nh < sl->preheight && get_b_rand()) nh++; } else { while(nh <= sl->height && get_b_rand()) nh++; } /* Now we have the new height at which we wish to insert our new node */ /* Let us make sure that our tree is a least that tall (grow if necessary)*/ for(;sl->height<nh;sl->height++) { sl->top->up = (struct skiplistnode *)malloc(sizeof(struct skiplistnode)); assert(sl->top->up); sl->top->up->down = sl->top; sl->top = sl->topend = sl->top->up; sl->top->prev = sl->top->next = sl->top->nextindex = sl->top->previndex = sl->top->up = NULL; sl->top->data = NULL; sl->top->sl = sl; } ch = sl->height; /* Find the node (or node after which we would insert) */ /* Keep a stack to pop back through for insertion */ m = sl->top; stack = (struct skiplistnode **)malloc(sizeof(struct skiplistnode *)*(nh)); stacki=0; while(m) { int compared=-1; if(m->next) compared=comp(data, m->next->data); if(compared == 0) { free(stack); return 0; } if((m->next == NULL) || (compared<0)) { /* FIXME: This if ch<=nh test looks unnecessary. ch==nh at beginning of while(m) */ if(ch<=nh) { /* push on stack */ stack[stacki++] = m; } m = m->down; ch--; } else { m = m->next; } } /* Pop the stack and insert nodes */ p = tmp = NULL; for(;stacki>0;stacki--) { m = stack[stacki-1]; tmp = (struct skiplistnode *)malloc(sizeof(struct skiplistnode)); tmp->next = m->next; if(m->next) m->next->prev=tmp; tmp->prev = m; tmp->up = NULL; tmp->nextindex = tmp->previndex = NULL; tmp->down = p; if(p) p->up=tmp; tmp->data = data; tmp->sl = sl; m->next = tmp; /* This sets ret to the bottom-most node we are inserting */ if(!p) { ret=tmp; sl->size++; } p = tmp; } free(stack); if(tmp && (tmp->prev == sl->topend)) { /* The last element on the top row is the new inserted one */ sl->topend = tmp; } if(ret && (ret->prev == sl->bottomend)) { /* The last element on the bottom row is the new inserted one */ sl->bottomend = ret; } if(sl->index != NULL) { /* this is a external insertion, we must insert into each index as well */ struct skiplistnode *p, *ni, *li; li=ret; for(p = sl_getlist(sl->index); p; sl_next(sl->index, &p)) { ni = sl_insert((Skiplist *)p->data, ret->data); assert(ni); Alarm(SKIPLIST, "Adding %p to index %p\n", ret->data, p->data); li->nextindex = ni; ni->previndex = li; li = ni; } } /* JRS: move size increment above to where node is inserted else { sl->size++; } */ /*sl_print_struct(sl, "AI: ");*/ return ret; }
int main( int argc, char **argv ) { sl_List sl; int count; int i; maa_init( argv[0] ); if (argc == 1) { count = 10; } else if (argc != 2 ) { fprintf( stderr, "usage: sltest count\n" ); return 1; } else { count = atoi( argv[1] ); } printf( "Running test for count of %d\n", count ); sl = sl_create( compare, key, NULL ); for (i = 1; i < count; i++) { printf( "adding %d\n", i ); sl_insert( sl, (void *) (intptr_t) i ); #ifdef DUMP _sl_dump( sl ); #endif } sl_iterate( sl, print ); printf( "\n" ); sl_delete( sl, (void *)5 ); sl_iterate( sl, print ); printf( "\n" ); sl_insert( sl, (void *)0 ); sl_iterate( sl, print ); printf( "\n" ); sl_insert( sl, (void *)66 ); sl_iterate( sl, print ); printf( "\n" ); sl_insert( sl, (void *)100 ); sl_iterate( sl, print ); printf( "\n" ); sl_insert( sl, (void *)-1 ); sl_iterate( sl, print ); printf( "\n" ); sl_insert( sl, (void *)5 ); sl_iterate( sl, print ); printf( "\n" ); sl_insert( sl, (void *)67 ); sl_iterate( sl, print ); printf( "\n" ); sl_insert( sl, (void *)68 ); sl_iterate( sl,print ); printf( "\n" ); sl_insert( sl, (void *)65 ); sl_iterate( sl, print ); printf( "\n" ); sl_destroy( sl ); return 0; }
LocatorNode_t *locator_list_add (LocatorList_t *list, LocatorKind_t kind, const unsigned char *addr, uint32_t port, uint32_t scope_id, Scope_t scope, unsigned flags, unsigned sproto) { LocSearchData data; LocatorNode_t **npp, *np; LocatorRef_t *rp, *p; int is_new; data.kind = kind; data.addr = addr; data.port = port; lock_take (loc_lock); npp = sl_insert (&loc_list, &data, &is_new, loc_cmp); if (!npp) { warn_printf ("locator_list_add: not enough memory for list node!"); lock_release (loc_lock); return (NULL); } if (is_new) { np = mds_pool_alloc (&mem_blocks [MB_LOCATOR]); if (!np) { warn_printf ("locator_list_add: not enough memory for locator node!"); #ifdef LIST_DELETE_NODE sl_delete_node (&loc_list, npp); #else sl_delete (&loc_list, &data, loc_cmp); #endif lock_release (loc_lock); return (NULL); } np->users = 0; np->locator.kind = kind; np->locator.port = port; memcpy (np->locator.address, addr, sizeof (np->locator.address)); np->locator.scope_id = scope_id; np->locator.scope = scope; np->locator.flags = flags; np->locator.sproto = sproto; np->locator.intf = 0; np->locator.handle = 0; *npp = np; } else { np = *npp; if (np->locator.scope_id != scope_id || (np->locator.scope && scope && np->locator.scope != scope) || /*(np->locator.flags && flags && (np->locator.flags & LOCF_MFLAGS) != (flags & LOCF_MFLAGS)) ||*/ (np->locator.sproto && sproto && np->locator.sproto != sproto)) log_printf (LOC_ID, 0, "locator_list_add: incompatible locator attributes for %s, " "%u:%u, %u:%u, 0x%x:0x%x, %u:%u!\r\n", locator_str (&np->locator), np->locator.scope_id, scope_id, np->locator.scope, scope, np->locator.flags, flags, np->locator.sproto, sproto); if (!np->locator.scope_id && scope_id) np->locator.scope_id = scope_id; if (!np->locator.scope && scope) np->locator.scope = scope; if (flags && np->locator.flags != flags) np->locator.flags |= flags; if (!np->locator.sproto && sproto) np->locator.sproto = sproto; /* Check if already in list. */ for (rp = *list; rp; rp = rp->next) if (rp->data == np) { /* Already there! */ lock_release (loc_lock); return (0); } } #ifdef LOG_LOCATORS log_printf (LOC_ID, 0, "LOC: locator_list_add (list=%p, %s)\r\n", (void *) list, locator_str (&np->locator)); #endif rp = mds_pool_alloc (&mem_blocks [MB_LOCREF]); if (!rp) { warn_printf ("locator_list_add: not enough memory for locator reference!\r\n"); if (is_new) { mds_pool_free (&mem_blocks [MB_LOCATOR], np); #ifdef LIST_DELETE_NODE sl_delete_node (&loc_list, npp); #else sl_delete (&loc_list, &data, loc_cmp); #endif } lock_release (loc_lock); return (NULL); } rp->next = NULL; rp->data = np; np->users++; lock_release (loc_lock); if (*list) { for (p = *list; p->next; p = p->next) ; p->next = rp; } else *list = rp; return (np); }
static char *test_speed_compare(void) { struct _timeb start; struct _timeb finish; unsigned long sl_time_taken; unsigned long kl_time_taken; int keys[10000]; int vals[10000]; int test_keys[100]; sl *slist = sl_create(); kl *klist = kl_create(); int *v; _ftime(&start); /* generate long list (same for both) */ for(int i = 0; i < 10000; i++) { keys[i] = rand(); vals[i] = rand(); } for(int i = 0; i < 100; i++) { test_keys[i] = rand() % 10000; } /* fill lists with it (time this) */ _ftime(&start); for(int i = 0; i < 10000; i++) { kl_insert(klist, keys[i], &vals[i]); } _ftime(&finish); printf("kl: inserted 10,000 keys in %lums\n", ftime_diff(&start, &finish)); _ftime(&start); for(int i = 0; i < 10000; i++) { sl_insert(slist, keys[i], &vals[i]); } _ftime(&finish); printf("sl: inserted 10,000 keys in %lums\n", ftime_diff(&start, &finish)); /* find random values in it (same for both) n times, average time taken */ _ftime(&start); for(int i = 0; i < 1000; i++) { for(int j = 0; j < 100; j++) { v = sl_find(slist, keys[test_keys[j]]); } } _ftime(&finish); sl_time_taken = ftime_diff(&start, &finish); _ftime(&start); for(int i = 0; i < 1000; i++) { for(int j = 0; j < 100; j++) { v = kl_find(klist, keys[test_keys[j]]); } } _ftime(&finish); kl_time_taken = ftime_diff(&start, &finish); printf("sl: found 100,000 keys in %fs, %.2fkeys/s\n", sl_time_taken/1000.0, 100.0*100000/sl_time_taken); printf("kl: found 100,000 keys in %fs, %.2fkeys/s\n\n", kl_time_taken/1000.0, 100.0*100000/kl_time_taken); mu_assert("average sl find speed is slower than kl", sl_time_taken < kl_time_taken); sl_destroy(slist); kl_destroy(klist); return 0; }