1. py1_bject --> A simple package of long
typedef struct{PyObject_HEADlong ob_ival;} PyIntObject;
PyInt_Type --> py1_bject type object. Object-related meta information is actually stored in the type object corresponding to the object.
PyTypeObject PyInt_Type = {PyObject_HEAD_INIT(&PyType_Type)0,“int”,//…}
Operations supported by py1_bject
Int_dealloc // Delete the py1_bject object int_free // Delete the py1_bject object int_repr // convert it to the PyString object int_hash // obtain the HASH value int_print // print the py1_bject object int_compare // compare int_as_number/value operate int_methods // member functions
Py1_bject is a fixed-length object and an immutable object --> because it is immutable, every py1_bject object in the object pool can be shared freely without worrying about being modified.
2. Create and maintain a py1_bject object
Three ways to create a Python object through Python C API
PyObject *PyInt_FromLong(long ival)PyObject *PyInt_FromString(char *s, char **pend, int base)#ifdef Py_USING_UNICODEPyObject *PyInt_FromUnicode(Py_Unicode *s, int length, int base)#endif
PyInt_FromString and PyInt_FromUnicode use the Adaptor Pattern idea in the design mode to perform Interface Conversion for the core creation function PyInt_FromLong of the integer object.
3. Integer Object pool
Small integer object --> cache pool
Large integer object --> dedicated memory pool used in turn
The demarcation points between a small integer object and a large integer object
#ifndf NSMALLPOSINTS#define NSMALLPOSINTS257#endif#ifndef NSMALLNEGINTS#define NSMALLNEGINTS5#endif#if NSMALLNEGINTS + NSMALLPOSINTS > 0static PyIntObject *small_ints[NSMALLPOSINTS + NSMALLPOSINTS];#endif
3.1 General integer Object pool (large integer Object pool)
PyIntBlock Structure
# Define BLOCK_SIZE 1000/* 1 K less typical malloc overhead */# define BHEAD_SIZE 8/* Enough for a 64-bit pointer */# define n_1_bjects (BLOCK_SIZE-BHEAD_SIZE) /sizeof (pyeffecbject) struct _ intblock {struct _ intblock * next; pyeffecbject objects [n_effecbjects] ;}; typedef struct _ intblock PyIntBlock; static PyIntBlock * block_list = NULL; // maintain the one-way list of PyIntBlock static py1_bject * free_list = NULL; // manage all idle memory in objects of all blocks
PyInt_FromLong Function
1. If the small integer Object pool mechanism is activated, try to use the small integer Object pool
2. If you can use a small integer Object pool, use a general integer Object pool.
Fill_free_list
1. Apply for a new PyIntBlock Structure
2. Connect all py1_bject objects in objects through pointers to form a linked list with free_list as the header.
Tp_dealloc
When a py1_bject object is destroyed, the memory occupied by it is not released by the system, but is linked to the free memory linked list maintained by free_list.
Q: Isn't ob_type used to point to a type object? In fill_free_list, it is used to form a linked list. Who will point to a type object and how can I call operations corresponding to a type object without a type object? Why should we form a linked list?
Resolution: In fill_free_list, the objects (namely, the pyintbject array) in the applied PyIntBlock space has not been initialized, that is, it is not used, and the ob_type is useless, so it can be used to form a linked list. When a new PyIntBlock is created, ob_type points to PyInt_Type. I don't know what I understand here. If I understand it right, there will be a problem in Figure 2-7 in the book. The created PyIntBlock should not have a pointer to the free memory space, only when it is destroyed will it point to free memory again
The linked list is mainly used to maintain idle memory blocks in objects. The table header of the linked list is directed by free_list.
3.2 small integer Object pool
Call the _ PyInt_Init function in pythonrun. c (during python environment initialization) to initialize the small integer Object pool.
4. Hack py1_bject
Self-experiment results: