private void AllocPage(IByteBuf buf, int newSize, int size) { int idx; PoolPageList pageList; if (IsTiny(newSize)) { idx = (newSize >> 4) - 1; pageList = tinyPoolPages[idx]; } else { idx = IntEx.Log2(newSize >> 10); pageList = smallPoolPages[idx]; } var page = pageList.GetNextAvailPage(); if (page != null) { long handle = page.Alloc(newSize); if (handle > -1) { page.Chunk.BytebufInit(buf, handle, newSize, size); useables += newSize; } return; } //1,如果缓存中没有elemsize=size的page //2,如果从缓冲中分配失败 //1和2都满足,那么会重新分配一个新的page page = AllocNewPage(buf, newSize, size); if (page == null) { return; } pageList.AddLast(page); }
/// <summary> /// 更新bitmap,并返回当前的 /// </summary> /// <returns></returns> private int GetHandleAndUpdateBitMap() { // //方法1:先遍历数组,再遍历位 //优点:思路简单 //缺点:极端条件下最高可能遍历512次 // //for (int i = 0; i < bitmap.Length; i++) //{ // for (int j = 0; j < 64; j++) // { // //注意是1L不是1 // long mask = 1L << j; // if ((bitmap[i] & mask) == 0) // { // bitmap[i] |= mask; // return (i << 6) + j; //i*64+j // } // } //} //return -1; // //方法2:采用位运算 //优点:最多只需要遍历8次就能获得结果 //缺点:不易理解 // int result = -1; for (int i = 0; i < bitmap.Length; i++) { long b = bitmap[i]; if (b != 0) { /* * 获得当前long的第一个1开始的值 * 比如: * 10010001,计算得到1 * 10010010,计算得到10 * 10010100,计算得到100 */ long mask = b & ~(b - 1); /* * 关闭位 * 比如:bitmap[i]=10010100,mask=00000100 * 10010100 ^ 00000100 = 10010000 将第2号位的1置0 */ bitmap[i] ^= mask; /* * 为了方便传值,我们使用一个long类型来携带分配的信息 * (更清晰简单的办法是直接返回mask和索引i),这里我们将 * mask和i浓缩到一个long类型中来传递 * * 根据掩码mask和索引i计算出具体的位数,因为long型的 * mask只有一个1,所以我们只需要得到值为1的序号就OK了 */ int h32 = (int)(mask >> 32); //高32位的值 int l32 = (int)mask; //低32位的值 //如果1在高位 if (h32 > 0) { //在高位时需要+32 //i<<6 = i*64 表示在第几号long中 return(IntEx.Log2(h32) + 32 + (i << 6)); } //如果1在低位 else { return(IntEx.Log2(l32) + (i << 6)); } } } return(result); }