62 lines
include/lru_cache.h
Declares LruCache with eviction callback contract.
// LruCache: thread-safe fixed-capacity LRU cache with eviction notification.
#pragma once
#include <functional>
#include <list>
#include <mutex>
#include <optional>
#include <string>
#include <unordered_map>
 
// Thread-safe fixed-capacity LRU cache (string keys, string values).
// When the cache is full, the least-recently-used entry is evicted before
// the new entry is inserted.
//
// Eviction callback contract:
//   - Called with (key, value) of the evicted entry by value.
//   - Invoked without holding the internal lock, so it is safe to call
//     insert() or get() from within the callback without deadlocking.
class LruCache {
public:
  using EvictFn = std::function<void(const std::string&, const std::string&)>;
 
  // Parameters:
  //   capacity - maximum number of entries before eviction occurs
  //   onEvict  - optional callback invoked for each evicted entry
  // Returns: new LruCache ready to accept insert() calls
  explicit LruCache(std::size_t capacity, EvictFn onEvict = {});
 
  // Parameters:
  //   key   - cache key to insert or update
  //   value - value to store; evicts LRU entry when cache is at capacity
  // Returns: void
  void insert(const std::string& key, std::string value);
 
  // Parameters:
  //   key - cache key to look up
  // Returns: copy of the cached value, or nullopt if not present
  std::optional<std::string> get(const std::string& key);
 
  // Parameters: none
  // Returns: number of entries currently in the cache
  std::size_t size() const;
 
  // Parameters: none
  // Returns: true if the cache contains no entries
  bool empty() const;
 
  // Parameters: none
  // Returns: void; removes all entries without invoking the eviction callback
  void clear();
 
private:
  struct Entry {
    std::string value; // cached value string
    std::list<std::string>::iterator listIt; // position in the LRU order list
  };
 
  std::size_t                                   capacity_; // maximum entry count
  std::list<std::string>                        order_;    // LRU order; front is MRU
  std::unordered_map<std::string, Entry>        map_;      // key → entry index
  mutable std::mutex                            mu_;       // guards all mutable state
  EvictFn                                       onEvict_;  // caller eviction hook
};