UDT源码剖析(八)之Cache
在UDT源代码中,作者使用了std::vector
和std::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;
}