From c79f51b20b4db8d35a19849263cf9478f483ad55 Mon Sep 17 00:00:00 2001 From: rachytski Date: Sat, 30 Jul 2011 12:43:27 +0300 Subject: [PATCH] added LockElem/UnlockElem methods and tests. --- base/base_tests/mru_cache_test.cpp | 17 ++++++++++ base/mru_cache.hpp | 52 ++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/base/base_tests/mru_cache_test.cpp b/base/base_tests/mru_cache_test.cpp index 323b0438d1..3bb673b05c 100644 --- a/base/base_tests/mru_cache_test.cpp +++ b/base/base_tests/mru_cache_test.cpp @@ -28,4 +28,21 @@ UNIT_TEST(MRUCache_Test) CHECK(m.HasElem(2) == false, ()); CHECK(m.HasElem(1) == true, ()); + + m.LockElem(1); + m.Add(4, 16, 2); + + CHECK(m.HasElem(4) == true, ()); + CHECK(m.Find(4, false) == 16, ()); + + CHECK(m.HasElem(3) == false, ()); + CHECK(m.HasElem(1) == true, ()); + + m.UnlockElem(1); + // 2 is still older than 4, so check this + + m.Add(5, 25, 2); + CHECK(m.HasElem(5) == true, ()); + CHECK(m.HasElem(4) == true, ()); + CHECK(m.HasElem(1) == false, ()); } diff --git a/base/mru_cache.hpp b/base/mru_cache.hpp index c6cb03f934..1a0339a8c3 100644 --- a/base/mru_cache.hpp +++ b/base/mru_cache.hpp @@ -1,6 +1,7 @@ #pragma once #include "../std/unordered_map.hpp" +#include "../std/list.hpp" #include "assert.hpp" namespace my @@ -26,6 +27,7 @@ namespace my { ValueT m_value; size_t m_weight; + bool m_locked; typename list_t::iterator m_it; }; @@ -46,6 +48,19 @@ namespace my return m_map.find(key) != m_map.end(); } + void LockElem(KeyT const & key) + { + ASSERT(HasElem(key), ()); + m_map[key].m_locked = true; + } + + void UnlockElem(KeyT const & key) + { + ASSERT(HasElem(key), ()); + ASSERT(m_map[key].m_locked, ()); + m_map[key].m_locked = false; + } + ValueT const & Find(KeyT const & key, bool DoTouch = true) { typename map_t::iterator it = m_map.find(key); @@ -79,7 +94,7 @@ namespace my { typename map_t::iterator it = m_map.find(key); - if (it != m_map.end()) + if (it != m_map.end() && !it->second.m_locked) { m_curWeight -= it->second.m_weight; m_list.erase(it->second.m_it); @@ -93,20 +108,45 @@ namespace my if (HasElem(key)) Remove(key); + typename list::iterator it = (++m_list.rbegin()).base(); + while (m_curWeight + weight > m_maxWeight) { if (m_list.empty()) return; - KeyT k = m_list.back(); - m_list.pop_back(); - m_curWeight -= m_map[k].m_weight; - ValueTraitsT::Evict(m_map[k].m_value); - m_map.erase(k); + + KeyT k = *it; + + /// erasing only unlocked elements + if (!m_map[k].m_locked) + { + m_curWeight -= m_map[k].m_weight; + ValueTraitsT::Evict(m_map[k].m_value); + m_map.erase(k); + + typename list::iterator nextIt = it; + if (nextIt != m_list.begin()) + { + --nextIt; + m_list.erase(it); + it = nextIt; + } + else + { + m_list.erase(it); + break; + } + } + else + --it; } + ASSERT(m_curWeight + weight <= m_maxWeight, ()); + m_list.push_front(key); m_map[key].m_weight = weight; m_map[key].m_value = val; + m_map[key].m_locked = false; m_map[key].m_it = m_list.begin(); m_curWeight += weight; }