Cachemere
Modular Caching Library for C++
|
This page is meant to guide you through the implementation of custom policies.
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.
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.
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.
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.
Policies do not need to take any steps to ensure thread-safety. The cache will properly protect policies to ensure no concurrent operations occur.
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.
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.
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.
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.
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.
true
does not guarantee that the object matching the candidate
key will be inserted in cache.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.
Iterator victim_end() const
Should return an end iterator. Used to determine whether victim iteration is complete.