UDT源码剖析(八)之Cache

在UDT源代码中,作者使用了std::vectorstd::list组装了一个缓存系统,本来在纠结要不要列出来,没有啥技术含量,不过为了完整性,还是列出来吧...

CCache

class CCache
{
private:
   std::list<T*> m_StorageList;     //定义一个链表,链表中的指针指向缓存的对象(真实存储位置)
   typedef typename std::list<T*>::iterator ItemPtr;    //指向链表结点的iterator
   typedef std::list<ItemPtr> ItemPtrList;  //将指向ListNode的iterator封装成一个链表
   std::vector<ItemPtrList> m_vHashPtr;//HASH表

   int m_iMaxSize;  //最大的数量
   int m_iHashSize; //HASH值
   int m_iCurrSize; //当前数量

   udt_pthread_mutex_t m_Lock;
};
class CInfoBlock
{
public:
   uint32_t m_piIP[4];		//机器可读的IP地址,为了IPV4只占32位,IPV6全部占用
   int m_iIPversion;		// IP version
   uint64_t m_ullTimeStamp;	//上一次更新的时间
   int m_iRTT;			//RTT
   int m_iBandwidth;		//估计的带宽
   int m_iLossRate;		//平均丢失速率
   int m_iReorderDistance;	//数据包重新排序距离
   double m_dInterval;		//分组间时间,就是数据包发送的间隔时间,用于拥塞控制
   double m_dCWnd;		//拥塞窗口大小用于拥塞控制
}
  • 初始化:CCache(int size = 1024)
CCache(int size = 1024):
   m_iMaxSize(size),    
   m_iHashSize(size * 3),
   m_iCurrSize(0)
   {
      m_vHashPtr.resize(m_iHashSize);   //使用resize在HASH中预留位置
      CGuard::createMutex(m_Lock);
   }
  • 销毁:~CCache()
   ~CCache()
   {
      clear();
      CGuard::releaseMutex(m_Lock);
   }

-在HASH'中进行查找: int lookup(T* data)

   int lookup(T* data)
   {
      CGuard cacheguard(m_Lock);

      int key = data->getKey();    //获得在HASH中的索引位置
      if (key < 0)
         return -1;
      if (key >= m_iMaxSize) //如果大于1024
         key %= m_iHashSize; //求在HASH中的位置,找到想应的链表

      const ItemPtrList& item_list = m_vHashPtr[key];
      for (typename ItemPtrList::const_iterator i = item_list.begin(); i != item_list.end(); ++ i)
      {
         if (*data == ***i)
         {
            *data = ***i;
            return 0;
         }
      }

      return -1;
   }
  • 更新缓存: int update(T* data)
   int update(T* data)
   {
      CGuard cacheguard(m_Lock);

      int key = data->getKey();    //同上,先在HASH中寻找槽
      if (key < 0)
         return -1;
      if (key >= m_iMaxSize)
         key %= m_iHashSize;

      T* curr = NULL;

      ItemPtrList& item_list = m_vHashPtr[key];    
      for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i)
      {
         if (*data == ***i)
         {
            // update the existing entry with the new value
            ***i = *data;   //找到想要找到的i
            curr = **i;

            // remove the current entry
            m_StorageList.erase(*i);    //删除i
            item_list.erase(i);

            // re-insert to the front
            m_StorageList.push_front(curr); //调整i的位置,因为最近访问,修改存储位置,加快访问速度
            item_list.push_front(m_StorageList.begin());

            return 0;
         }
      }

      // create new entry and insert to front
      curr = data->clone(); //如果没有找到,就直接插入
      m_StorageList.push_front(curr);
      item_list.push_front(m_StorageList.begin());

      ++ m_iCurrSize;   //增加当前的数量
      
      //如果当前的缓存已经溢出,删除最后一个缓存对象
      if (m_iCurrSize >= m_iMaxSize)
      {
         T* last_data = m_StorageList.back();
         int last_key = last_data->getKey() % m_iHashSize;

         item_list = m_vHashPtr[last_key];
         for (typename ItemPtrList::iterator i = item_list.begin(); i != item_list.end(); ++ i)
         {
            if (*last_data == ***i)
            {
               item_list.erase(i);
               break;
            }
         }

         last_data->release();
         delete last_data;
         m_StorageList.pop_back();
         -- m_iCurrSize;
      }

      return 0;
   }
  • 清理所有缓存: void clear()
   void clear()
   {
      for (typename std::list<T*>::iterator i = m_StorageList.begin(); i != m_StorageList.end(); ++ i)
      {
         (*i)->release();
         delete *i;
      }
      m_StorageList.clear();
      for (typename std::vector<ItemPtrList>::iterator i = m_vHashPtr.begin(); i != m_vHashPtr.end(); ++ i)
         i->clear();
      m_iCurrSize = 0;
    }

posted on 2018-06-16 18:30  ukernel  阅读(448)  评论(0编辑  收藏  举报

导航