Skip to content

Commit

Permalink
implement for_each for LRU cache
Browse files Browse the repository at this point in the history
  • Loading branch information
chenhao-ye committed Oct 6, 2024
1 parent a650d0b commit b032947
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 7 deletions.
34 changes: 32 additions & 2 deletions include/gcache/lru_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@ class LRUCache {
template <typename Fn>
void for_each(Fn&& fn);

// For each item in the LRU list, call fn(key, handle) in LRU order
template <typename Fn>
void for_each_lru(Fn&& fn);

// For each item in the LRU list, call fn(key, handle) in MRU order
template <typename Fn>
void for_each_mru(Fn&& fn);

// For each item in the in-use list, call fn(key, handle)
template <typename Fn>
void for_each_in_use(Fn&& fn);

// Set pin to be true to pin the returned node so it won't be recycled by
// LRU; a pinned node must be unpinned later by calling release().

Expand Down Expand Up @@ -257,8 +269,26 @@ inline void LRUCache<Key_t, Value_t, Hash>::init(size_t capacity, Fn&& fn) {
template <typename Key_t, typename Value_t, typename Hash>
template <typename Fn>
inline void LRUCache<Key_t, Value_t, Hash>::for_each(Fn&& fn) {
in_use_.for_each(fn);
lru_.for_each(fn);
for_each_lru(fn);
for_each_in_use(fn);
}

template <typename Key_t, typename Value_t, typename Hash>
template <typename Fn>
inline void LRUCache<Key_t, Value_t, Hash>::for_each_lru(Fn&& fn) {
for (auto h = lru_.next; h != &lru_; h = h->next) fn(h);
}

template <typename Key_t, typename Value_t, typename Hash>
template <typename Fn>
inline void LRUCache<Key_t, Value_t, Hash>::for_each_mru(Fn&& fn) {
for (auto h = lru_.prev; h != &lru_; h = h->prev) fn(h);
}

template <typename Key_t, typename Value_t, typename Hash>
template <typename Fn>
inline void LRUCache<Key_t, Value_t, Hash>::for_each_in_use(Fn&& fn) {
for (auto h = in_use_.next; h != &in_use_; h = h->next) fn(h);
}

template <typename Key_t, typename Value_t, typename Hash>
Expand Down
5 changes: 0 additions & 5 deletions include/gcache/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@ class LRUNode {
return os << h.key << " (refs=" << h.refs << ", hash=" << h.hash << ")";
}

template <typename Fn>
void for_each(Fn fn) {
for (auto h = next; h != this; h = h->next) fn(h->key, h);
}

// print a list; this must be a dummy list head
std::ostream &print_list(std::ostream &os) const {
auto h = next;
Expand Down
27 changes: 27 additions & 0 deletions tests/test_lru.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <cassert>
#include <cstdint>
#include <iostream>
#include <ostream>
#include <stdexcept>

#include "gcache/lru_cache.h"
Expand Down Expand Up @@ -156,8 +157,34 @@ void test() {
std::cout << "\n=== Expect: lru: [5, 8, 9], in_use: [6] ===\n";
std::cout << cache;

// test for_each
std::cout << "\n=== Expect: { 5: 555, 8: 888, 9: 999, 6: 666, } ===\n";
std::cout << "{ ";
cache.for_each([](LRUCache<uint32_t, uint32_t, hash1>::Handle_t h) {
std::cout << h.get_key() << ": " << *h << ", ";
assert(key == value);
});
std::cout << "}" << std::endl;

cache.release(h6);

// test for checkpoint and recover
std::vector<std::pair<uint32_t, uint32_t>> ckpt;
cache.for_each_lru([&ckpt](LRUCache<uint32_t, uint32_t, hash1>::Handle_t h) {
ckpt.emplace_back(h.get_key(), *h);
});

LRUCache<uint32_t, uint32_t, hash1> cache_recovered;
cache_recovered.init(4);
for (auto& [key, value] : ckpt) {
auto h = cache_recovered.insert(key, true);
assert(h);
*h = value;
cache_recovered.release(h);
}
std::cout << "\n=== Expect: { 5: 555, 8: 888, 9: 999, 6: 666, } ===\n";
std::cout << cache_recovered;

std::cout << std::flush;
}

Expand Down

0 comments on commit b032947

Please sign in to comment.