这两天遇到一个事情,server分配房间号,client希望填充空洞,就是已经申请了1 2 3 4 5都被申请;现在2 4 被释放;下一次要从2 4开始分配;
这就让我想到了linux pid的分配策略,在32为下最大默认2^32-1;会用数组记录分配情况,但是一直++,如果发现超过最大值,就开始回滚了;
现在只需要做了一个小的改动,每次分配、释放都试图更新curFreepid,这样下次就从这个开始检测分配就行:
#include <stdio.h>
/* max pid, equal to 2^15=32768 */
#define PID_MAX_DEFAULT 0x8000
/* page size = 2^12 = 4K */
#define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define BITS_PER_BYTE 8
//4k*8 32768
#define BITS_PER_PAGE (PAGE_SIZE * BITS_PER_BYTE)
//7fff
//0111 1111 1111 1111
#define BITS_PER_PAGE_MASK (BITS_PER_PAGE - 1)
typedef struct pidmap
{
unsigned int nr_free;
char page[4096];
} pidmap_t;
static pidmap_t pidmap = { PID_MAX_DEFAULT, {0}};
static int curFree_pid = 0;
static int test_and_set_bit(int offset, void *addr)
{
unsigned long mask = 1UL << (offset & (sizeof(unsigned long) * BITS_PER_BYTE - 1));
unsigned long *p = ((unsigned long*)addr) + (offset >> (sizeof(unsigned long) + 1));
unsigned long old = *p;
*p = old | mask;
return (old & mask) != 0;
}
static void clear_bit(int offset, void *addr)
{
unsigned long mask = 1UL << (offset & (sizeof(unsigned long) * BITS_PER_BYTE - 1));//取offset的后31位数据,并左移
unsigned long *p = ((unsigned long*)addr) + (offset >> (sizeof(unsigned long) + 1));//+优先级高于>>
unsigned long old = *p;
*p = old & ~mask;
}
static int find_next_zero_bit(void *addr, int size, int offset)
{
unsigned long *p;
unsigned long mask;
while (offset < size)
{
p = ((unsigned long*)addr) + (offset >> (sizeof(unsigned long) + 1));
mask = 1UL << (offset & (sizeof(unsigned long) * BITS_PER_BYTE - 1));
if ((~(*p) & mask))
{
break;
}
++offset;
}
return offset;
}
static int alloc_pidmap()
{
if (!pidmap.nr_free)
{
return -1;
}
int offset = find_next_zero_bit(&pidmap.page, BITS_PER_PAGE, curFree_pid);
if (BITS_PER_PAGE != offset && !test_and_set_bit(offset, &pidmap.page))
{
--pidmap.nr_free;
curFree_pid = find_next_zero_bit(&pidmap.page, BITS_PER_PAGE, offset);
return offset;
}
return -1;
}
static void free_pidmap(int pid)
{
int offset = pid & BITS_PER_PAGE_MASK;
pidmap.nr_free++;
clear_bit(offset, &pidmap.page);
if (curFree_pid > offset){
curFree_pid = offset;
}
}
int main()
{
int i;
for (i = 0; i < 20; ++i) {
int a = alloc_pidmap();
printf("%d ", a);
}
printf("\nfree ");
free_pidmap(18);
free_pidmap(5);
printf("\nalloc ");
for (i = 0; i < 10; ++i) {
int a = alloc_pidmap();
printf("%d ", a);
}
return 0;
}
经测试没问题。