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