本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie
1. PyIntObject --> long的一个简单包装
typedef struct{ PyObject_HEAD long ob_ival; } PyIntObject;
PyInt_Type --> PyIntObject的类型对象。与对象相关的元信息实际上都是保存在与对象对应的类型对象中的
PyTypeObject PyInt_Type = { PyObject_HEAD_INIT(&PyType_Type) 0, “int”, //… }
PyIntObject 所支持的操作
int_dealloc //删除 PyIntObject 对象 int_free //删除 PyIntObject 对象 int_repr //转化成 PyString 对象 int_hash //获得 HASH 值 int_print //打印 PyIntObject 对象 int_compare //比较操作 int_as_number //数值操作 int_methods //成员函数PyIntObject是定长对象,不可变对象 --> 因为不可变,所以对象池里的每一个PyIntObject对象都能够被任意地共享,不用担心被修改。
2. PyIntObject对象的创建和维护
Python C API创建PyIntObject的三种途径
PyObject *PyInt_FromLong(long ival) PyObject *PyInt_FromString(char *s, char **pend, int base) #ifdef Py_USING_UNICODE PyObject *PyInt_FromUnicode(Py_Unicode *s, int length, int base) #endifPyInt_FromString和PyInt_FromUnicode利用了设计模式中的Adaptor Pattern思想对整数对象的核心创建函数PyInt_FromLong进行了接口转换
3. 整数对象池
小整数对象--> 缓存池缓存
大整数对象--> 专用内存池轮流使用
小整数对象与大整数对象的分界点
#ifndf NSMALLPOSINTS #define NSMALLPOSINTS 257 #endif #ifndef NSMALLNEGINTS #define NSMALLNEGINTS 5 #endif #if NSMALLNEGINTS + NSMALLPOSINTS > 0 static PyIntObject *small_ints[NSMALLPOSINTS + NSMALLPOSINTS]; #endif3.1 通用整数对象池(大整数对象池)
PyIntBlock的结构
#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;//维护PyIntBlock的单向列表 static PyIntObject *free_list = NULL;//管理全部block的objects中的所有空闲内存PyInt_FromLong函数
1. 如果小整数对象池机制被激活,则尝试使用小整数对象池
2. 如果还能使用小整数对象池由使用通用的整数对象池。
fill_free_list
1. 申请一个新的PyIntBlock结构
2. 将objects中的所有PyIntObject对象通过指针依次连接起来,形成一个free_list为表头的链表
tp_dealloc
一个PyIntObject对象被销毁时,它所占有的内存并不会被系统释放,而是变成了*内存被链入了free_list所维护的*内存链表
问题:ob_type不是用来指向类型对象的吗,在fill_free_list中它却被用来形成链表,那谁来指向类型对象,没有类型对象又怎么调用类型对应的操作?为什么要形成链表?
解析:在fill_free_list中,申请的PyIntBlock空间中的objects(即PyIntObject数组)还没有初始化,即没有被使用,ob_type放着没用,所以可以用来形成链表。当创建新的PyIntBlock时,ob_type会指向PyInt_Type。这里不知道我的理解对不对,如果我的理解对的话,书上的图2-7就有问题,已经创建了的PyIntBlock不应该有一个指向*内存空间的指针,只有当它被销毁才会重新指向*内存空间
形成的链表主要是用来维护还没有objects中空闲的内存块,链表的表头由free_list所指向。
3.2 小整数对象池
在pythonrun.c(python环境初始化时)中调用_PyInt_Init函数完成小整数对象池的初始化。
自己实验的结果: