00001 #include "TargetPhraseCollectionCache.h"
00002
00003 namespace Moses
00004 {
00005 using std::vector;
00006
00007 TPCollCache::
00008 TPCollCache(size_t capacity)
00009 {
00010 m_qfirst = m_qlast = m_cache.end();
00011 m_capacity = capacity;
00012 UTIL_THROW_IF2(m_capacity <= 2, "Cache capacity must be > 1!");
00013 }
00014
00015 SPTR<TPCollWrapper>
00016 TPCollCache::
00017 get(uint64_t key, size_t revision)
00018 {
00019 using namespace boost;
00020 unique_lock<shared_mutex> lock(m_lock);
00021
00022 #if 0
00023 size_t ctr=0;
00024 std::cerr << "BEFORE" << std::endl;
00025 for (cache_t::iterator m = m_qfirst; m != m_cache.end(); m = m->second->next)
00026 {
00027 std::cerr << ++ctr << "/" << m_cache.size() << " "
00028 << (m->second->key == key ? "*" : " ")
00029 << m->second->key << " "
00030 << m->second.use_count();
00031 if (m->second->prev != m_cache.end())
00032 std::cerr << " => " << m->second->prev->second->key;
00033 std::cerr << std::endl;
00034 }
00035 std::cerr << "\n" << std::endl;
00036 #endif
00037
00038 std::pair<uint64_t, SPTR<TPCollWrapper> > e(key, SPTR<TPCollWrapper>());
00039 std::pair<cache_t::iterator, bool> foo = m_cache.insert(e);
00040 SPTR<TPCollWrapper>& ret = foo.first->second;
00041 if (ret && m_cache.size() > 1 && m_qlast != foo.first)
00042 {
00043 if (m_qfirst == foo.first) m_qfirst = ret->next;
00044 else ret->prev->second->next = ret->next;
00045 if (m_qlast != foo.first)
00046 ret->next->second->prev = ret->prev;
00047 }
00048 if (!ret || ret->revision != revision)
00049 {
00050 ret.reset(new TPCollWrapper(key,revision));
00051 }
00052 if (m_cache.size() == 1)
00053 {
00054 m_qfirst = m_qlast = foo.first;
00055 ret->prev = m_cache.end();
00056 }
00057 else if (m_qlast != foo.first)
00058 {
00059 ret->prev = m_qlast;
00060 m_qlast->second->next = foo.first;
00061 m_qlast = foo.first;
00062 }
00063 ret->next = m_cache.end();
00064
00065 #if 0
00066 std::cerr << "AFTER" << std::endl;
00067 ctr=0;
00068 for (cache_t::iterator m = m_qfirst; m != m_cache.end(); m = m->second->next)
00069 {
00070 std::cerr << ++ctr << "/" << m_cache.size() << " "
00071 << (m->second->key == key ? "*" : " ")
00072 << m->second->key << " "
00073 << m->second.use_count();
00074 if (m->second->prev != m_cache.end())
00075 std::cerr << " => " << m->second->prev->second->key;
00076 std::cerr << std::endl;
00077 }
00078 std::cerr << "\n" << std::endl;
00079 #endif
00080
00081 if (m_cache.size() > m_capacity)
00082 {
00083 // size_t ctr = 0;
00084 // size_t oldsize = m_cache.size();
00085 while (m_cache.size() > m_capacity && m_qfirst->second.use_count() == 1)
00086 {
00087 m_qfirst = m_qfirst->second->next;
00088 // std::cerr << "erasing " << ++ctr << "/" << m_cache.size() << " "
00089 // << m_qfirst->second->key << std::endl;
00090 m_cache.erase(m_qfirst->second->prev);
00091 }
00092 // if (oldsize > m_cache.size()) std::cerr << "\n" << std::endl;
00093 }
00094 return ret;
00095 } // TPCollCache::get(...)
00096
00097 TPCollWrapper::
00098 TPCollWrapper(uint64_t key_, size_t revision_)
00099 : revision(revision_), key(key_)
00100 { }
00101
00102 TPCollWrapper::
00103 ~TPCollWrapper()
00104 { }
00105
00106 } // namespace