diff --git a/inc/hgl/type/LRUCache.cpp b/inc/hgl/type/LRUCache.cpp new file mode 100644 index 00000000..74e969bc --- /dev/null +++ b/inc/hgl/type/LRUCache.cpp @@ -0,0 +1,354 @@ +#ifndef HGL_TYPE_LRU_CACHE_CPP +#define HGL_TYPE_LRU_CACHE_CPP + +#include +namespace hgl +{ + /** + * 本类构造函数 + * @param value 缓冲区最大数据量 + */ + template + LRUCache::LRUCache(int value) + { + if(value<=0) + { + LOG_ERROR(OS_TEXT("ActiveChain缓冲区大小被设置<=0")); + + value=3; + } + + count=0; + max_count=value; + + start_item=nullptr; + end_item=nullptr; + } + + template + LRUCache::~LRUCache() + { + Clear(); + } + + template + void LRUCache::SetMaxCount(int value) + { + if(value<=0) + { + LOG_ERROR(OS_TEXT("ActiveChain缓冲区大小被设置<=0,此次设置无效!")); + } + else + max_count=value; + } + + template + bool LRUCache::Create(const F &,T &) + { + return true; + } + + template + void LRUCache::Clear(const F &,T &) + { + } + + template + void LRUCache::ClearEnd() + { + LruItem *temp=end_item->prev; + + Clear(end_item->key,end_item->value); + + delete end_item; + + end_item=temp; + + if(end_item) //如果只有一个数据,end_item会为NULL + end_item->next=nullptr; + else + { + #ifdef _DEBUG + if(count!=1) + { + LOG_ERROR(OS_TEXT("ActiveChain出错,end_item=nullptr,count!=1")); + } + #endif// + start_item=nullptr; //如果end_item为空,start_item也应该为空 + } + + count--; + } + + /** + * 添加一个数据 + * @param key 数据标识 + * @param value 数据 + */ + template + LRUCacheItem *LRUCache::Add(const F &key,const T &value) + { + LruItem *temp; + + while(count>=max_count)ClearEnd(); //满了,清除超出的数据 + + temp=new LruItem; + temp->key=key; + temp->value=value; + + temp->prev=nullptr; + temp->next=start_item; + + if(start_item) //如果还没有数据,start会为NULL + start_item->prev=temp; + + start_item=temp; //将当前数据设成start_item + + count++; + + if(!end_item) + { + #ifdef _DEBUG //理由上end_item为NULL时应该是没有数据 + if(count!=1) + { + LOG_ERROR(OS_TEXT("ActiveChain出错,end_item=nullptr,count!=1")); + } + else + #endif//_DEBUG + end_item=start_item; + } + + return(temp); + } + + template + void LRUCache::MoveToStart(LruItem *item) + { + if(item==start_item) + return; + //不是首节点,这个情况下count肯定>1 + if(item!=end_item) //也不是尾节点,这个情况下count肯定>2 + { + if(item->next) + item->next->prev=item->prev; + + if(item->prev) + item->prev->next=item->next; + + start_item->prev=item; + + item->prev=nullptr; + item->next=start_item; + + start_item=item; + } + else //为尾节点 + { + end_item=end_item->prev; + end_item->next=nullptr; + + item->prev=nullptr; + item->next=start_item; + + start_item->prev=item; + + start_item=item; + } + } + + /** + * 取得一个数据,在没有数据时,不自动创建数据,返回false + * @param key 数据标识 + * @param value 数据存放地 + * @param mts 是否对数据调频 + * @return 是否取得数据成功 + */ + template + bool LRUCache::Find(const F &key,T &value,bool mts) + { + if(count<=0)return(false); + + int n=count; + LruItem *temp=start_item; + + while(n--) + { + if(temp->key==key) + { + value=temp->value; + + if(mts) + MoveToStart(temp); + + return(true); + } + else + temp=temp->next; + } + + return(false); + } + + /** + * 取得一个数据,如果数据不存在,调用Create创建数据,如失败返回false + * @param key 数据标识 + * @param value 数据存放地 + * @param mts 是否对数据动态调频 + * @return 是否取得数据 true/false + */ + template + bool LRUCache::Get(const F &key,T &value,bool mts) + { + if(Find(key,value,mts)) + return(true); + + while(count>=max_count)ClearEnd(); //满了,清除超出的数据 + + if(Create(key,value)) + { + Add(key,value); + + return(true); + } + + return(false); + } + + /** + * 清数所有数据 + */ + template + void LRUCache::Clear() + { + if(count<=0)return; + + int n=0; + LruItem *temp=start_item; + + while(temp) + { + LruItem *obj=temp; + + Clear(obj->key,obj->value); + + temp=obj->next; + + delete obj; + n++; + } + + if(n!=count) + { + LOG_ERROR(OS_TEXT("LRUCache Count=")+OSString(count)+OS_TEXT(",Clear=")+OSString(n)); + } + + count=0; + start_item=nullptr; + end_item=nullptr; + } + + template + void LRUCache::Delete(LruItem *obj) + { + if(!obj)return; + + Clear(obj->key,obj->value); + + if(count>1) + { + if(obj==start_item) + { + start_item=obj->next; + + start_item->prev=nullptr; + } + else + if(obj==end_item) + { + end_item=obj->prev; + + end_item->next=nullptr; + } + else + { + obj->prev->next=obj->next; + + obj->next->prev=obj->prev; + } + } + else + { + start_item=nullptr; + end_item=nullptr; + } + + delete obj; + + count--; + } + + template + void LRUCache::DeleteByKey(const F &key) + { + if(count<=0)return; + + int n=count; + LruItem *temp=start_item; + + while(n--) + { + if(temp->key==key) + { + Delete(temp); + return; + } + + temp=temp->next; + } + } + + template + void LRUCache::DeleteByValue(T &value) + { + if(count<=0)return; + + int n=count; + LruItem *temp=start_item; + + while(n--) + { + if(temp->value==value) + { + Delete(temp); + return; + } + + temp=temp->next; + } + } + +// template +// bool LRUCache::Update(const F &key,T &value) +// { +// if(Find(key,value,false)) +// { +// LruItem *obj=temp; +// +// Clear(obj->key,obj->value); +// +// Create(obj->key,obj->value); +// +// return(true); +// } +// +// if(Create(key,value)) +// { +// Add(key,value); +// +// return(true); +// } +// +// return(false); +// } +}//namespace hgl +#endif//HGL_TYPE_LRU_CACHE_CPP diff --git a/inc/hgl/type/LRUCache.h b/inc/hgl/type/LRUCache.h new file mode 100644 index 00000000..9167e81e --- /dev/null +++ b/inc/hgl/type/LRUCache.h @@ -0,0 +1,78 @@ +#ifndef HGL_TYPE_LRU_CACHE_INCLUDE +#define HGL_TYPE_LRU_CACHE_INCLUDE + +#include +namespace hgl +{ + template struct LRUCacheItem + { + F key; //识别标识 + + T value; //数据 + + LRUCacheItem *prev, //前一数据 + *next; //后一数据 + };//template struct LRUCacheItem + + /** + * 最近使用数据缓冲区管理模板(当缓冲区满时,将最长时间没有使用的清除)
+ * 现这个模板使用双头链表,每次添加或使用的数据会被移到链表的最前端。
+ * 这样使用率最低的数据会被存在链表的最末端,当缓冲区满时,最末端的数据将会被清除。 + */ + template class LRUCache ///缓冲区管理模板(以最终使用时间为基准) + { + public: + + using LruItem=LRUCacheItem; + + protected: + + LruItem *start_item, //首数据 + *end_item; //尾数据 + + int count,max_count; + + protected: + + virtual bool Create(const F &,T &); ///<创建数据 + virtual void Clear(const F &,T &); ///<清除数据 + + void MoveToStart(LruItem *); ///<移动某一个数据到最前面 + + void Delete(LruItem *); ///<清除某一个数据 + + void ClearEnd(); ///<清除最后一个数据 + + public: + + const int GetCount ()const{return count;} ///<取得当前有多少数据 + const int GetMaxCount ()const{return max_count;} ///<取得最大可以有多少数据 + virtual void SetMaxCount (int); ///<设置最大可以有多少数据 + int GetFreeCount()const{return max_count-count;} ///<取得当前缓冲区剩于量 + + public: + + LRUCache(int); + virtual ~LRUCache(); + + virtual LruItem * Add (const F &,const T &); ///<增加一个数据 + virtual bool Find (const F &,T &,bool=true); ///<取得一个数据(如果没有不会自动创建) + virtual bool Get (const F &,T &,bool=true); ///<取得一个数据(如果没有会自动创建) + void Clear (); ///<清除所有数据 + LruItem * GetEnd (bool mts=true) ///<取最后一项 + { + LruItem *obj=end_item; + + if(mts) + MoveToStart(obj); + + return(obj); + } + + void DeleteByKey(const F &); + void DeleteByValue(T &); +// bool Update (const F &,T &); ///<更新数据 + };//template class LRUCache +}//namespace hgl +#include +#endif//HGL_TYPE_LRU_CACHE_INCLUDE