1 #ifndef GENESIS_UTILS_CONTAINERS_MRU_CACHE_H_
2 #define GENESIS_UTILS_CONTAINERS_MRU_CACHE_H_
39 #include <unordered_map>
99 template<
typename Key,
typename T >
112 using iterator =
typename std::list< value_type >::iterator;
160 return cache_.begin();
168 return cache_.cbegin();
186 return cache_.cend();
194 return cache_.cbegin();
202 return cache_.cend();
214 assert( lookup_.size() == cache_.size() );
215 return lookup_.size();
225 assert( capacity_ == 0 || lookup_.size() <= capacity_ );
234 return lookup_.empty();
257 return cache_misses_;
289 auto const lit = lookup_.find( key );
292 if( lit != lookup_.end() ) {
294 return promote_and_get_( lit->second );
300 assert( lookup_.count( key ) == 0 );
302 lookup_[ key ] = cache_.begin();
303 assert( cache_.size() == lookup_.size() );
310 assert( ! cache_.empty() );
311 return cache_.begin()->second;
357 std::lock_guard<std::mutex> lock( mutex_ );
360 auto const lit = lookup_.find( key );
363 if( lit != lookup_.end() ) {
366 return promote_and_get_( lit->second );
372 std::list< value_type > tmp_list;
379 std::lock_guard<std::mutex> lock( mutex_ );
383 auto const lit = lookup_.find( key );
387 if( lit != lookup_.end() ) {
389 return promote_and_get_( lit->second );
395 assert( lookup_.count( key ) == 0 );
396 assert( tmp_list.size() == 1 );
397 cache_.splice( cache_.begin(), tmp_list, tmp_list.begin() );
398 lookup_[ key ] = cache_.begin();
399 assert( cache_.size() == lookup_.size() );
405 assert( ! cache_.empty() );
406 return cache_.begin()->second;
417 return lookup_.count( key ) > 0;
450 std::lock_guard<std::mutex> lock( mutex_ );
454 assert( capacity_ == 0 ||
size() <= capacity_ );
463 std::lock_guard<std::mutex> lock( mutex_ );
466 for(
auto& elem : cache_ ) {
486 if( capacity_ == 0 ) {
491 while(
size() > capacity_ ) {
494 assert( lookup_.size() == cache_.size() );
497 assert( cache_.size() > 1 );
499 auto& last = cache_.back();
503 lookup_.erase( last.first );
508 assert( lookup_.size() == cache_.size() );
509 assert( lookup_.size() <=
capacity() );
520 assert( ! cache_.empty() );
523 if( cache_it != cache_.begin() ) {
524 cache_.splice( cache_.begin(), cache_, cache_it );
528 return cache_it->second;
570 std::list< value_type > cache_;
578 std::unordered_map< key_type, iterator > lookup_;
588 size_t cache_hits_ = 0;
593 size_t cache_misses_ = 0;
600 #endif // include guard