工具类分析-rak::partial_queue

来源:互联网 发布:目前最火爆的网络手游 编辑:程序博客网 时间:2024/06/10 23:01

说明:通过ChunkStatistics统计出所有chunk的供应数后,下一步就是要针对peer将其拥有的chunk按照稀缺度分layer,形象一点就是将chunk按照贵重程度放到7(num_layers)层玲珑宝塔(m_layers)中,不过这个宝塔有点特别,越往下越贵重。(重的东西是应该放下面)。每层的区间范围分别为 第0层到第7层

[0,1) [1,3) [3,7) [7,15) [15,31) [31,63) [63,127) [127,255)

注意:
1. 每层(layer)的数目有限m_maxLayerSize,seeder 32个,leecher 8个,但是在同一层中的chunk可能大于m_maxLayerSize,这称为overflowing,算法的处理是不弹出上一层的chunk,而是返回false,参考prepare_pop函数
2. 第0层(最底层)含义:chunk统计数为0的(只有seeder才可能插入)

成员变量:

  mapped_type*        m_data;        //按层排列的chunk index列表  size_type           m_maxLayerSize;//每层的最大个数  size_type           m_index;       //当前拥有成员的最底层,从第0层开始  size_type           m_ceiling;     //可插入层的最大统计值,从最高层的最大值开始  size_pair_type      m_layers[num_layers];//first 本层已经pop的chunk数,second 本层总共的chunk数
核心函数:
//构造,ls: 每层最大允许的chunk index数inline void partial_queue::enable(size_type ls) {  if (ls == 0)    throw std::logic_error("partial_queue::enable(...) ls == 0.");  delete [] m_data;  m_data = new mapped_type[ls * num_layers];  m_maxLayerSize = ls;}//销毁inline void partial_queue::disable() {  delete [] m_data;  m_data = NULL;  m_maxLayerSize = 0;}//清空inline void partial_queue::clear() {  if (m_data == NULL)    return;  m_index = 0;  m_ceiling = ceiling(num_layers - 1);  std::memset(m_layers, 0, num_layers * sizeof(size_pair_type));}

/************************************************************************
增加一个成员
参数:            key:   成员身价,chunk的统计数,值越少越值钱  
                   value: 成员ID号,chunk index
说明:
    本算法按照chunk统计数,将chunk放到不同的层,如果中间某一层满了,继续往低一层放,直到使最低层满了,则整个queue满了(只有seeder可能做到),插入后m_index指向有chunk的最低层,m_ceiling表示可插入的层最高统计值
    本函数由ChunkSelector调用
************************************************************************/
inline bool partial_queue::insert(key_type key, mapped_type value) {
  if(key>= m_ceiling)
    return false;

  size_type idx= 0; 

  //找到layer
 
while(key>= ceiling(idx))
    ++idx;

  m_index= std::min(m_index, idx);

  // Currently don't allow overflow.
 
if(is_layer_full(idx))
    throwstd::logic_error("partial_queue::insert(...) layer already full."); 
    //记录chunk index
 
m_data[m_maxLayerSize* idx+ m_layers[idx].second] = value;
  m_layers[idx].second++;

  if(is_layer_full(idx))
    // 如果是第0层满了,则表示整个queue满了,否则到低一层
  
m_ceiling= idx> 0 ? ceiling(idx- 1) : 0;

  return true;
}

//定位到有un-popped chunk的最低层 inline bool partial_queue::prepare_pop() {  while (m_layers[m_index].first == m_layers[m_index].second) {        //is_layer_full(m_index)表示overflowed,表示在当前layer的chunk大于m_maxLayerSize    if (is_layer_full(m_index) || m_index + 1 == num_layers)      return false;    m_index++;  }  return true;}//获得chunk indexinline partial_queue::mapped_type partial_queue::pop() {  if (m_index >= num_layers || m_layers[m_index].first >= m_layers[m_index].second)    throw std::logic_error("partial_queue::pop() bad state.");  return m_data[m_index * m_maxLayerSize + m_layers[m_index].first++];}
原创粉丝点击