python使用双层单向链表存储大整数对象代码实现

源码如下:

构建双层单向链表,分别通过block_list和free_list指针进行访问,该部分就不详细描述。

其中block_list指向当前PyIntBlock对象,其next指针指向已经使用过的PyIntBlock对象;

PyIntBlock内存存在object数据,是一段连续内存。其通过PyObject特殊的数据结构,强制将后一个PyIntObject中的ob_type指针指向前一个PyIntObject内存空间地址(局部放弃类型安全的坚持)。(从后往前使用)从而外部访问进行指针偏移,仅需要赋值当前ob_type指针(需要强转为PyIntObject指针类型)。

/* Integers are quite normal objects, to make object handling uniform.
   (Using odd pointers to represent integers would save much space
   but require extra checks for this special case throughout the code.)
   Since a typical Python program spends much of its time allocating
   and deallocating integers, these operations should be very fast.
   Therefore we use a dedicated allocation scheme with a much lower
   overhead (in space and time) than straight malloc(): a simple
   dedicated free list, filled when necessary with memory from malloc().

   block_list is a singly-linked list of all PyIntBlocks ever allocated,
   linked via their next members.  PyIntBlocks are never returned to the
   system before shutdown (PyInt_Fini).

   free_list is a singly-linked list of available PyIntObjects, linked
   via abuse of their ob_type members.
*/

#define BLOCK_SIZE	1000	/* 1K less typical malloc overhead */
#define BHEAD_SIZE	8	/* Enough for a 64-bit pointer */
#define N_INTOBJECTS	((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyIntObject))

struct _intblock {
	struct _intblock *next;
	PyIntObject objects[N_INTOBJECTS];
};

typedef struct _intblock PyIntBlock;

static PyIntBlock *block_list = NULL;
static PyIntObject *free_list = NULL;

static PyIntObject *
fill_free_list(void)
{
	PyIntObject *p, *q;
	/* Python's object allocator isn't appropriate for large blocks. */
	p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));
	if (p == NULL)
		return (PyIntObject *) PyErr_NoMemory();
	((PyIntBlock *)p)->next = block_list;
	block_list = (PyIntBlock *)p;
	/* Link the int objects together, from rear to front, then return
	   the address of the last int object in the block. */
	p = &((PyIntBlock *)p)->objects[0];
	q = p + N_INTOBJECTS;
	while (--q > p)
	    // make a list, ob_type of last PyIntObject point
		// to (last - 1) PyIntObject, and util ob_type of second
		// PyIntObject point to first PyIntObject.
		q->ob_type = (struct _typeobject *)(q-1);
	q->ob_type = NULL;
	return p + N_INTOBJECTS - 1;
}

如上实现就存在一个问题,如果某一个PyIntObject释放了,这个空间如何再次被利用呢?这就隐藏在释放的处理逻辑里面了。

static void
int_dealloc(PyIntObject *v)
{
	if (PyInt_CheckExact(v)) {
        // insert free PyIntObject to last of free_list.
        // freed PyIntObject is new start of free list, and
        // v->ob_type is next PyIntObject space.
		v->ob_type = (struct _typeobject *)free_list;
		free_list = v;
	}
	else
		v->ob_type->tp_free((PyObject *)v);
}

扩展阅读:

Python整数对象实现原理详解 - 第一PHP社区

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值