填充空洞的ID分配策略

这两天遇到一个事情,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;
}

经测试没问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值