RETURN 0 - ok -1 - out of memory */
| 473 | -1 - out of memory |
| 474 | */ |
| 475 | static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node, |
| 476 | uint bucket, LF_PINS *pins) |
| 477 | { |
| 478 | uint parent= my_clear_highest_bit(bucket); |
| 479 | LF_SLIST *dummy= (LF_SLIST *)my_malloc(sizeof(LF_SLIST), MYF(MY_WME)); |
| 480 | LF_SLIST **tmp= 0, *cur; |
| 481 | LF_SLIST * volatile *el= _lf_dynarray_lvalue(&hash->array, parent); |
| 482 | if (unlikely(!el || !dummy)) |
| 483 | return -1; |
| 484 | if (*el == NULL && bucket && |
| 485 | unlikely(initialize_bucket(hash, el, parent, pins))) |
| 486 | return -1; |
| 487 | dummy->hashnr= my_reverse_bits(bucket) | 0; /* dummy node */ |
| 488 | dummy->key= dummy_key; |
| 489 | dummy->keylen= 0; |
| 490 | if ((cur= linsert(el, hash->charset, dummy, pins, LF_HASH_UNIQUE))) |
| 491 | { |
| 492 | my_free(dummy); |
| 493 | dummy= cur; |
| 494 | } |
| 495 | my_atomic_casptr((void **)node, (void **)&tmp, dummy); |
| 496 | /* |
| 497 | note that if the CAS above failed (after linsert() succeeded), |
| 498 | it would mean that some other thread has executed linsert() for |
| 499 | the same dummy node, its linsert() failed, it picked up our |
| 500 | dummy node (in "dummy= cur") and executed the same CAS as above. |
| 501 | Which means that even if CAS above failed we don't need to retry, |
| 502 | and we should not free(dummy) - there's no memory leak here |
| 503 | */ |
| 504 | return 0; |
| 505 | } |
no test coverage detected