/* Allocate and return an new object. DESCRIPTION Pop an unused object from the stack or malloc it is the stack is empty. pin[0] is used, it's removed on return. */ void *_lf_alloc_new(LF_PINS *pins) { LF_ALLOCATOR *allocator= (LF_ALLOCATOR *)(pins->pinbox->free_func_arg); uchar *node; for (;;) { do { node= allocator->top; _lf_pin(pins, 0, node); } while (node != allocator->top && LF_BACKOFF); if (!node) { node= (void *)my_malloc(allocator->element_size, MYF(MY_WME)); if (allocator->constructor) allocator->constructor(node); #ifdef MY_LF_EXTRA_DEBUG if (likely(node != 0)) my_atomic_add32(&allocator->mallocs, 1); #endif break; } if (my_atomic_casptr((void **)(char *)&allocator->top, (void *)&node, anext_node(node))) break; } _lf_unpin(pins, 0); return node; }
/* DESCRIPTION searches for a node as identified by hashnr/keey/keylen in the list that starts from 'head' RETURN 0 - not found node - found NOTE it uses pins[0..2], on return the pin[2] keeps the node found all other pins are removed. */ static LF_SLIST *lsearch(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, const uchar *key, uint keylen, LF_PINS *pins) { CURSOR cursor; int res= lfind(head, cs, hashnr, key, keylen, &cursor, pins); if (res) _lf_pin(pins, 2, cursor.curr); _lf_unpin(pins, 0); _lf_unpin(pins, 1); return res ? cursor.curr : 0; }
/* DESCRIPTION Search for hashnr/key/keylen in the list starting from 'head' and position the cursor. The list is ORDER BY hashnr, key RETURN 0 - not found 1 - found NOTE cursor is positioned in either case pins[0..2] are used, they are NOT removed on return */ static int lfind(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins) { uint32 cur_hashnr; const uchar *cur_key; uint cur_keylen; intptr link; retry: cursor->prev= (intptr *)head; do { /* PTR() isn't necessary below, head is a dummy node */ cursor->curr= (LF_SLIST *)(*cursor->prev); _lf_pin(pins, 1, cursor->curr); } while (*cursor->prev != (intptr)cursor->curr && LF_BACKOFF); for (;;) { if (unlikely(!cursor->curr)) return 0; /* end of the list */ do { /* QQ: XXX or goto retry ? */ link= cursor->curr->link; cursor->next= PTR(link); _lf_pin(pins, 0, cursor->next); } while (link != cursor->curr->link && LF_BACKOFF); cur_hashnr= cursor->curr->hashnr; cur_key= cursor->curr->key; cur_keylen= cursor->curr->keylen; if (*cursor->prev != (intptr)cursor->curr) { (void)LF_BACKOFF; goto retry; } if (!DELETED(link)) { if (cur_hashnr >= hashnr) { int r= 1; if (cur_hashnr > hashnr || (r= my_strnncoll(cs, (uchar*) cur_key, cur_keylen, (uchar*) key, keylen)) >= 0) return !r; } cursor->prev= &(cursor->curr->link); _lf_pin(pins, 2, cursor->curr); } else { /* we found a deleted node - be nice, help the other thread and remove this deleted node */ if (my_atomic_casptr((void **) cursor->prev, (void **)(char*) &cursor->curr, cursor->next)) _lf_alloc_free(pins, cursor->curr); else { (void)LF_BACKOFF; goto retry; } } cursor->curr= cursor->next; _lf_pin(pins, 1, cursor->curr); } }