| 494 | |
| 495 | template <typename H> |
| 496 | void |
| 497 | IntrusiveHashMap<H>::insert(value_type *v) { |
| 498 | auto key = H::key_of(v); |
| 499 | Bucket *bucket = this->bucket_for(key); |
| 500 | value_type *spot = bucket->_v; |
| 501 | bool mixed_p = false; // Found a different key in the bucket. |
| 502 | |
| 503 | if (nullptr == spot) { // currently empty bucket, set it and add to active list. |
| 504 | _list.append(v); |
| 505 | bucket->_v = v; |
| 506 | _active_buckets.append(bucket); |
| 507 | } else { |
| 508 | value_type *limit = bucket->limit(); |
| 509 | |
| 510 | // First search the bucket to see if the key is already in it. |
| 511 | while (spot != limit && !H::equal(key, H::key_of(spot))) { |
| 512 | spot = H::next_ptr(spot); |
| 513 | } |
| 514 | if (spot != bucket->_v) { |
| 515 | mixed_p = true; // found some other key, it's going to be mixed. |
| 516 | } |
| 517 | if (spot != limit) { |
| 518 | // If an equal key was found, walk past those to insert at the upper end of the range. |
| 519 | do { |
| 520 | spot = H::next_ptr(spot); |
| 521 | } while (spot != limit && H::equal(key, H::key_of(spot))); |
| 522 | if (spot != limit) { // something not equal past last equivalent, it's going to be mixed. |
| 523 | mixed_p = true; |
| 524 | } |
| 525 | } |
| 526 | |
| 527 | _list.insert_before(spot, v); |
| 528 | if (spot == bucket->_v) { // added before the bucket start, update the start. |
| 529 | bucket->_v = v; |
| 530 | } |
| 531 | bucket->_mixed_p = mixed_p; |
| 532 | } |
| 533 | ++bucket->_count; |
| 534 | |
| 535 | // auto expand if appropriate. |
| 536 | if ((AVERAGE == _expansion_policy && (_list.count() / _table.size()) > _expansion_limit) || |
| 537 | (MAXIMUM == _expansion_policy && bucket->_count > _expansion_limit && bucket->_mixed_p)) { |
| 538 | this->expand(); |
| 539 | } |
| 540 | } |
| 541 | |
| 542 | template <typename H> |
| 543 | auto |
no test coverage detected