| 438 | |
| 439 | template<Cache::EvictionPolicy policy> |
| 440 | size_t RLCacheShard<policy>::Invalidate(const Cache::InvalidationControl& ctl) { |
| 441 | DCHECK(initialized_); |
| 442 | size_t invalid_entry_count = 0; |
| 443 | size_t valid_entry_count = 0; |
| 444 | RLThreadState tstate; |
| 445 | |
| 446 | { |
| 447 | std::lock_guard<decltype(mutex_)> l(mutex_); |
| 448 | |
| 449 | // rl_.next is the oldest (a.k.a. least relevant) entry in the recency list. |
| 450 | RLHandle* h = rl_.next; |
| 451 | while (h != nullptr && h != &rl_ && |
| 452 | ctl.iteration_func(valid_entry_count, invalid_entry_count)) { |
| 453 | if (ctl.validity_func(h->key(), h->value())) { |
| 454 | // Continue iterating over the list. |
| 455 | h = h->next; |
| 456 | ++valid_entry_count; |
| 457 | continue; |
| 458 | } |
| 459 | // Copy the handle slated for removal. |
| 460 | RLHandle* h_to_remove = h; |
| 461 | // Prepare for next iteration of the cycle. |
| 462 | h = h->next; |
| 463 | |
| 464 | RL_Remove(h_to_remove); |
| 465 | table_.Remove(h_to_remove->key(), h_to_remove->hash()); |
| 466 | if (Unref(h_to_remove)) { |
| 467 | h_to_remove->next = tstate.to_remove_head; |
| 468 | tstate.to_remove_head = h_to_remove; |
| 469 | } |
| 470 | ++invalid_entry_count; |
| 471 | } |
| 472 | } |
| 473 | // Once removed from the lookup table and the recency list, the entries |
| 474 | // with no references left must be deallocated because Cache::Release() |
| 475 | // wont be called for them from elsewhere. |
| 476 | CleanupThreadState(&tstate); |
| 477 | return invalid_entry_count; |
| 478 | } |
| 479 | |
| 480 | template<Cache::EvictionPolicy policy> |
| 481 | vector<HandleBase*> RLCacheShard<policy>::Dump() { |