Hỗ trợ thu gom rác tuần hoàn¶
Sự hỗ trợ của Python trong việc phát hiện và thu thập rác bao gồm các tham chiếu vòng tròn yêu cầu sự hỗ trợ từ các loại đối tượng là "vùng chứa" cho các đối tượng khác cũng có thể là vùng chứa. Các loại không lưu trữ tham chiếu đến các đối tượng khác hoặc chỉ lưu trữ tham chiếu đến loại nguyên tử (chẳng hạn như số hoặc chuỗi), không cần cung cấp bất kỳ hỗ trợ rõ ràng nào cho việc thu gom rác.
Để tạo loại vùng chứa, trường tp_flags của đối tượng loại phải bao gồm Py_TPFLAGS_HAVE_GC và cung cấp cách triển khai trình xử lý tp_traverse. Nếu các phiên bản của loại này có thể thay đổi thì việc triển khai tp_clear cũng phải được cung cấp.
Py_TPFLAGS_HAVE_GCCác đối tượng có loại có bộ cờ này phải tuân thủ các quy tắc được ghi ở đây. Để thuận tiện, những đối tượng này sẽ được gọi là đối tượng chứa.
Trình xây dựng cho các loại vùng chứa phải tuân theo hai quy tắc:
Bộ nhớ cho đối tượng phải được phân bổ bằng
PyObject_GC_NewhoặcPyObject_GC_NewVar.Khi tất cả các trường có thể chứa tham chiếu đến các vùng chứa khác được khởi tạo, nó phải gọi
PyObject_GC_Track().
Tương tự, bộ giải phóng cho đối tượng phải tuân theo một cặp quy tắc tương tự:
Trước khi các trường tham chiếu đến các vùng chứa khác bị vô hiệu,
PyObject_GC_UnTrack()phải được gọi.Bộ nhớ của đối tượng phải được giải phóng bằng
PyObject_GC_Del().Cảnh báo
Nếu một loại thêm Py_TPFLAGS_HAVE_GC thì must sẽ triển khai ít nhất một trình xử lý
tp_traversehoặc sử dụng rõ ràng một trình xử lý từ lớp con hoặc các lớp con của nó.Khi gọi
PyType_Ready()hoặc một số API gọi gián tiếp nhưPyType_FromSpecWithBases()hoặcPyType_FromSpec(), trình thông dịch sẽ tự động điền vào các trườngtp_flags,tp_traversevàtp_clearnếu loại kế thừa từ một lớp thực hiện giao thức thu gom rác và lớp con not bao gồm cờPy_TPFLAGS_HAVE_GC.
-
PyObject_GC_New(TYPE, typeobj)¶
Tương tự như
PyObject_Newnhưng dành cho các đối tượng vùng chứa có bộ cờPy_TPFLAGS_HAVE_GC.Đừng gọi trực tiếp điều này để cấp phát bộ nhớ cho một đối tượng; thay vào đó hãy gọi loại
tp_allocslot.Khi điền vào vị trí
tp_alloccủa một loại,PyType_GenericAlloc()được ưu tiên hơn chức năng tùy chỉnh chỉ gọi macro này.Bộ nhớ được cấp phát bởi macro này phải được giải phóng bằng
PyObject_GC_Del()(thường được gọi thông qua khetp_freecủa đối tượng).
-
PyObject_GC_NewVar(TYPE, typeobj, size)¶
Tương tự như
PyObject_NewVarnhưng dành cho các đối tượng vùng chứa có bộ cờPy_TPFLAGS_HAVE_GC.Đừng gọi trực tiếp điều này để cấp phát bộ nhớ cho một đối tượng; thay vào đó hãy gọi loại
tp_allocslot.Khi điền vào vị trí
tp_alloccủa một loại,PyType_GenericAlloc()được ưu tiên hơn chức năng tùy chỉnh chỉ gọi macro này.Bộ nhớ được cấp phát bởi macro này phải được giải phóng bằng
PyObject_GC_Del()(thường được gọi thông qua khetp_freecủa đối tượng).
-
PyObject *PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size)¶
- Đây là API không ổn định. Nó có thể thay đổi mà không có cảnh báo trong các bản phát hành nhỏ.
Tương tự như
PyObject_GC_Newnhưng phân bổ byte extra_size ở cuối đối tượng (ở offsettp_basicsize). Bộ nhớ được phân bổ được khởi tạo về số 0, ngoại trừPython object header.Dữ liệu bổ sung sẽ được giải phóng cùng với đối tượng, nhưng nếu không thì nó không được Python quản lý.
Bộ nhớ được cấp phát bởi chức năng này phải được giải phóng bằng
PyObject_GC_Del()(thường được gọi thông qua khetp_freecủa đối tượng).Cảnh báo
Hàm này được đánh dấu là không ổn định vì cơ chế cuối cùng để dự trữ dữ liệu bổ sung sau một phiên bản vẫn chưa được quyết định. Để phân bổ số lượng trường khác nhau, thay vào đó, hãy ưu tiên sử dụng
PyVarObjectvàtp_itemsize.Added in version 3.12.
-
PyObject_GC_Resize(TYPE, op, newsize)¶
Thay đổi kích thước đối tượng được phân bổ bởi
PyObject_NewVar. Trả về đối tượng đã thay đổi kích thước thuộc loạiTYPE*(tham chiếu đến bất kỳ loại C nào) hoặcNULLkhi thất bại.op phải thuộc loại PyVarObject* và chưa được người thu thập theo dõi. newsize phải thuộc loại
Py_ssize_t.
-
void PyObject_GC_Track(PyObject *op)¶
- Một phần của ABI ổn định.
Thêm đối tượng op vào tập hợp các đối tượng chứa được bộ sưu tập theo dõi. Trình thu thập có thể chạy vào những thời điểm không mong muốn nên các đối tượng phải hợp lệ trong khi được theo dõi. Điều này sẽ được gọi khi tất cả các trường theo sau bởi trình xử lý
tp_traversetrở nên hợp lệ, thường ở gần cuối hàm tạo.
-
int PyObject_IS_GC(PyObject *obj)¶
Trả về khác 0 nếu đối tượng thực hiện giao thức thu gom rác, nếu không thì trả về 0.
Bộ thu gom rác không thể theo dõi đối tượng nếu hàm này trả về 0.
-
int PyObject_GC_IsTracked(PyObject *op)¶
- Một phần của ABI ổn định kể từ phiên bản 3.9.
Trả về 1 nếu loại đối tượng của op triển khai giao thức GC và op hiện đang được trình thu gom rác theo dõi và 0 nếu ngược lại.
Điều này tương tự với hàm Python
gc.is_tracked().Added in version 3.9.
-
int PyObject_GC_IsFinalized(PyObject *op)¶
- Một phần của ABI ổn định kể từ phiên bản 3.9.
Trả về 1 nếu loại đối tượng của op thực hiện giao thức GC và op đã được trình thu gom rác hoàn thiện và 0 nếu ngược lại.
Điều này tương tự với hàm Python
gc.is_finalized().Added in version 3.9.
-
void PyObject_GC_Del(void *op)¶
- Một phần của ABI ổn định.
Giải phóng bộ nhớ được phân bổ cho một đối tượng bằng
PyObject_GC_NewhoặcPyObject_GC_NewVar.Đừng gọi trực tiếp điều này để giải phóng bộ nhớ của đối tượng; thay vào đó hãy gọi loại
tp_freeslot.Không sử dụng điều này cho bộ nhớ được phân bổ bởi
PyObject_New,PyObject_NewVarhoặc các hàm phân bổ liên quan; thay vào đó hãy sử dụngPyObject_Free().Xem thêm
PyObject_Free()là hàm không tương đương với GC của hàm này.
-
void PyObject_GC_UnTrack(void *op)¶
- Một phần của ABI ổn định.
Xóa đối tượng op khỏi tập hợp các đối tượng chứa được bộ sưu tập theo dõi. Lưu ý rằng
PyObject_GC_Track()có thể được gọi lại trên đối tượng này để thêm nó trở lại tập hợp các đối tượng được theo dõi. Trình giải quyết (trình xử lýtp_dealloc) nên gọi điều này cho đối tượng trước khi bất kỳ trường nào được trình xử lýtp_traversesử dụng trở nên không hợp lệ.
Thay đổi trong phiên bản 3.8: Các macro _PyObject_GC_TRACK() và _PyObject_GC_UNTRACK() đã bị xóa khỏi C API công khai.
Trình xử lý tp_traverse chấp nhận tham số hàm thuộc loại này:
-
typedef int (*visitproc)(PyObject *object, void *arg)¶
- Một phần của ABI ổn định.
Loại hàm khách truy cập được chuyển tới trình xử lý
tp_traverse. Hàm này phải được gọi với đối tượng cần duyệt là object và tham số thứ ba cho trình xử lýtp_traverselà arg. Lõi Python sử dụng một số chức năng của khách truy cập để triển khai tính năng phát hiện rác theo chu kỳ; người dùng sẽ không cần phải viết các hàm truy cập của riêng mình.
Trình xử lý tp_traverse phải có loại sau:
-
typedef int (*traverseproc)(PyObject *self, visitproc visit, void *arg)¶
- Một phần của ABI ổn định.
Chức năng truyền tải cho một đối tượng container. Việc triển khai phải gọi hàm visit cho từng đối tượng được chứa trực tiếp bởi self, với các tham số cho visit là đối tượng được chứa và giá trị arg được truyền cho trình xử lý. Không được gọi hàm visit với đối số đối tượng
NULL. Nếu visit trả về giá trị khác 0 thì giá trị đó sẽ được trả về ngay lập tức.Chức năng truyền tải không được có bất kỳ tác dụng phụ nào. Việc triển khai không được sửa đổi số lượng tham chiếu của bất kỳ đối tượng Python nào cũng như không tạo hoặc hủy bất kỳ đối tượng Python nào.
Để đơn giản hóa việc viết trình xử lý tp_traverse, macro Py_VISIT() được cung cấp. Để sử dụng macro này, việc triển khai tp_traverse phải đặt tên chính xác cho các đối số của nó là visit và arg:
-
Py_VISIT(o)¶
Nếu PyObject* o không phải là
NULL, hãy gọi lệnh gọi lại visit, với các đối số o và arg. Nếu visit trả về giá trị khác 0 thì trả về giá trị đó. Khi sử dụng macro này, trình xử lýtp_traversetrông giống nhưint tĩnh my_traverse(Noddy *self, visitproc visit, void *arg) { Py_VISIT(tự->foo); Py_VISIT(tự->thanh); trả về 0; }
Trình xử lý tp_clear phải thuộc loại inquiry hoặc NULL nếu đối tượng là bất biến.
-
typedef int (*inquiry)(PyObject *self)¶
- Một phần của ABI ổn định.
Bỏ các tham chiếu có thể đã tạo ra chu kỳ tham chiếu. Các đối tượng bất biến không phải xác định phương thức này vì chúng không bao giờ có thể trực tiếp tạo các chu trình tham chiếu. Lưu ý rằng đối tượng vẫn phải hợp lệ sau khi gọi phương thức này (không chỉ gọi
Py_DECREF()trên một tham chiếu). Collector sẽ gọi phương thức này nếu phát hiện đối tượng này có liên quan đến một chu trình tham chiếu.
Kiểm soát trạng thái thu gom rác¶
C-API cung cấp các chức năng sau để kiểm soát quá trình thu gom rác.
-
Py_ssize_t PyGC_Collect(void)¶
- Một phần của ABI ổn định.
Thực hiện thu gom rác đầy đủ nếu trình thu gom rác được bật. (Lưu ý rằng
gc.collect()chạy nó vô điều kiện.)Trả về số đối tượng đã thu thập + không thể truy cập không thể thu thập được. Nếu trình thu gom rác bị vô hiệu hóa hoặc đã được thu thập, hãy trả về
0ngay lập tức. Lỗi trong quá trình thu thập rác được chuyển tớisys.unraisablehook. Chức năng này không đưa ra ngoại lệ.
-
int PyGC_Enable(void)¶
- Một phần của ABI ổn định kể từ phiên bản 3.10.
Kích hoạt trình thu gom rác: tương tự như
gc.enable(). Trả về trạng thái trước đó, 0 cho vô hiệu hóa và 1 cho kích hoạt.Added in version 3.10.
-
int PyGC_Disable(void)¶
- Một phần của ABI ổn định kể từ phiên bản 3.10.
Tắt trình thu gom rác: tương tự như
gc.disable(). Trả về trạng thái trước đó, 0 cho vô hiệu hóa và 1 cho kích hoạt.Added in version 3.10.
-
int PyGC_IsEnabled(void)¶
- Một phần của ABI ổn định kể từ phiên bản 3.10.
Truy vấn trạng thái của trình thu gom rác: tương tự như
gc.isenabled(). Trả về trạng thái hiện tại, 0 cho vô hiệu hóa và 1 cho kích hoạt.Added in version 3.10.
Truy vấn trạng thái của bộ thu gom rác¶
C-API cung cấp giao diện sau để truy vấn thông tin về trình thu gom rác.
-
void PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg)¶
- Đây là API không ổn định. Nó có thể thay đổi mà không có cảnh báo trong các bản phát hành nhỏ.
Chạy callback được cung cấp trên tất cả các đối tượng có khả năng GC trực tiếp. arg được chuyển tới tất cả các lệnh gọi callback.
Cảnh báo
Nếu các đối tượng mới được (hủy) phân bổ bởi lệnh gọi lại thì không xác định được liệu chúng có được truy cập hay không.
Việc thu gom rác bị vô hiệu hóa trong quá trình vận hành. Việc chạy một bộ sưu tập trong lệnh gọi lại một cách rõ ràng có thể dẫn đến hành vi không xác định, ví dụ: đến thăm cùng một đồ vật nhiều lần hoặc không ghé thăm lần nào.
Added in version 3.12.
-
typedef int (*gcvisitobjects_t)(PyObject *object, void *arg)¶
Loại chức năng khách truy cập được chuyển tới
PyUnstable_GC_VisitObjects(). arg giống với arg được chuyển choPyUnstable_GC_VisitObjects. Trả về1để tiếp tục lặp, trả về0để dừng lặp. Các giá trị trả về khác hiện được dành riêng nên hành vi trả về bất kỳ thứ gì khác không được xác định.Added in version 3.12.