Cachemere
Modular Caching Library for C++
Implementing Custom Policies

This page is meant to guide you through the implementation of custom policies.

Shared Characteristics

Construction Requirements

Insertion and eviction policies must be default-constructible. The constraint policy may take parameters, these parameters will be forwarded to the policy from the cache constructor.

Template Parameters

Cache policies are templates, which must take exactly three template parameters: typename Key, typename KeyHash, and typename Value. If a policy needs additional parameterization, cachemere::policy::bind can be used for partial specialization, allowing use with the cache.

Event Handlers

The policies may define the following event handlers to be notified of changes in the cache. These handlers do not all need to be implemented; a policy only needs to define the handlers that are relevant to its implementation. The cache will detect available handlers on its policies at compile-time, and will only call those that are defined.

  • void on_insert(K& key, cachemere::detail::Item<V>& item)

    Called immediately after a successful insertion in cache.

  • void on_update(K& key, cachemere::detail::Item<V>& item)

    Called immediately after an insertion of an item that was already in cache (which has the effect of updating its value).

  • void on_cache_hit(K& key, cachemere::detail::Item<V>& item)

    Called immediately after a cache hit (a successful call to cachemere::Cache::find).

  • template<typename KeyType> void on_cache_miss(const KeyView& key)

    Where KeyType is a type that hashes to the same value as its corresponding Key using KeyHash. Called immediately after a cache miss (an unsuccessful call to cachemere::Cache::find).

  • void on_evict(K& key)

    Called immediately before dropping the provided key from the cache. The call is done this way to allow policies to keep references to cached items instead of copies.

Lifetime Requirements

Policies can safely keep references to object keys given that they properly drop all references to that key upon receiving an on_evict event.

Policies can safely keep references to object values given that they properly drop all references to that value upon receiving an on_evict event. In addition, policies keeping references to values must swap the held reference with the updated reference when receiving an on_update event.

Warning
Keeping references to cache-owned keys or values without respecting the constraints above will result in undefined behavior.

Concurrency Requirements

Policies do not need to take any steps to ensure thread-safety. The cache will properly protect policies to ensure no concurrent operations occur.

Constraint Policy

In addition to the shared requirements above, a constraint policy must implement the following methods in order to be valid:

  • bool can_add(const Key& key, const Item<Value>& item)

    Should return true if the item can be inserted in the cache while still satisfying the constraint.

    Note
    Returning true guarantees that the object matching the key will be inserted in cache.
  • bool can_replace(const Key& key, const Item<Value>& old_item, const Item<Value>& new_item)

    Should return true if the value associated with key can be changed from old_item to new_item while still satisfying the constraint.

    Note
    Returning true guarantees that the object matching the key will be updated.
  • bool is_satisfied()

    Should return true if the constraint is currently satisfied. The cache uses this method after a constraint update (e.g. a cache resize) to determine whether items should be evicted to make some room.

Insertion Policy

In addition to the shared requirements above, an insertion policy must implement the following methods in order to be valid:

  • bool should_add(const Key& key)

    Should return true if the policy allows the specified key to be inserted in cache.

    Note
    Returning true guarantees that the object matching the key will be inserted in cache.
  • bool should_replace(const Key& victim, const Key& candidate)

    Should return true if the policy states that the candidate should replace the victim in cache.

    Note
    Returning true does not guarantee that the object matching the candidate key will be inserted in cache.

Eviction Policy

In addition to the shared requirements above, an eviction policy must implement the following methods in order to be valid:

  • Iterator victim_begin() const

    Should return an iterator pointing to the first key that should be evicted from the cache.

    Warning
    Returning a key from this iterator does not guarantee that the item will be evicted. The policy should only rely on event handlers to track which items are currently in cache.
  • Iterator victim_end() const

    Should return an end iterator. Used to determine whether victim iteration is complete.