| 420 | |
| 421 | template<Cache::EvictionPolicy policy> |
| 422 | Cache::Handle* CacheShard<policy>::Insert( |
| 423 | RLHandle* handle, |
| 424 | Cache::EvictionCallback* eviction_callback) { |
| 425 | // Set the remaining RLHandle members which were not already allocated during |
| 426 | // Allocate(). |
| 427 | handle->eviction_callback = eviction_callback; |
| 428 | // Two refs for the handle: one from CacheShard, one for the returned handle. |
| 429 | handle->refs.store(2, std::memory_order_relaxed); |
| 430 | UpdateMemTracker(handle->charge); |
| 431 | if (PREDICT_TRUE(metrics_)) { |
| 432 | metrics_->cache_usage->IncrementBy(handle->charge); |
| 433 | metrics_->inserts->Increment(); |
| 434 | } |
| 435 | |
| 436 | RLHandle* to_remove_head = nullptr; |
| 437 | { |
| 438 | std::lock_guard<decltype(mutex_)> l(mutex_); |
| 439 | |
| 440 | RL_Append(handle); |
| 441 | |
| 442 | RLHandle* old = table_.Insert(handle); |
| 443 | if (old != nullptr) { |
| 444 | RL_Remove(old); |
| 445 | if (Unref(old)) { |
| 446 | old->next = to_remove_head; |
| 447 | to_remove_head = old; |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | while (usage_ > capacity_ && rl_.next != &rl_) { |
| 452 | RLHandle* old = rl_.next; |
| 453 | RL_Remove(old); |
| 454 | table_.Remove(old->key(), old->hash); |
| 455 | if (Unref(old)) { |
| 456 | old->next = to_remove_head; |
| 457 | to_remove_head = old; |
| 458 | } |
| 459 | } |
| 460 | } |
| 461 | |
| 462 | // we free the entries here outside of mutex for |
| 463 | // performance reasons |
| 464 | while (to_remove_head != nullptr) { |
| 465 | RLHandle* next = to_remove_head->next; |
| 466 | FreeEntry(to_remove_head); |
| 467 | to_remove_head = next; |
| 468 | } |
| 469 | |
| 470 | return reinterpret_cast<Cache::Handle*>(handle); |
| 471 | } |
| 472 | |
| 473 | template<Cache::EvictionPolicy policy> |
| 474 | void CacheShard<policy>::Erase(const Slice& key, uint32_t hash) { |