mirror of
https://github.com/python/cpython
synced 2024-10-14 08:31:28 +00:00
bpo-39947: Hide implementation detail of trashcan macros (GH-18971)
Py_TRASHCAN_BEGIN_CONDITION and Py_TRASHCAN_END macro no longer access PyThreadState attributes, but call new private _PyTrash_begin() and _PyTrash_end() functions which hide implementation details.
This commit is contained in:
parent
309d7cc5df
commit
38965ec541
|
@ -385,11 +385,6 @@ PyAPI_DATA(PyTypeObject) _PyNotImplemented_Type;
|
||||||
*/
|
*/
|
||||||
PyAPI_DATA(int) _Py_SwappedOp[];
|
PyAPI_DATA(int) _Py_SwappedOp[];
|
||||||
|
|
||||||
/* This is the old private API, invoked by the macros before 3.2.4.
|
|
||||||
Kept for binary compatibility of extensions using the stable ABI. */
|
|
||||||
PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*);
|
|
||||||
PyAPI_FUNC(void) _PyTrash_destroy_chain(void);
|
|
||||||
|
|
||||||
PyAPI_FUNC(void)
|
PyAPI_FUNC(void)
|
||||||
_PyDebugAllocatorStats(FILE *out, const char *block_name, int num_blocks,
|
_PyDebugAllocatorStats(FILE *out, const char *block_name, int num_blocks,
|
||||||
size_t sizeof_block);
|
size_t sizeof_block);
|
||||||
|
@ -507,10 +502,23 @@ partially-deallocated object. To check this, the tp_dealloc function must be
|
||||||
passed as second argument to Py_TRASHCAN_BEGIN().
|
passed as second argument to Py_TRASHCAN_BEGIN().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* The new thread-safe private API, invoked by the macros below. */
|
/* This is the old private API, invoked by the macros before 3.2.4.
|
||||||
|
Kept for binary compatibility of extensions using the stable ABI. */
|
||||||
|
PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*);
|
||||||
|
PyAPI_FUNC(void) _PyTrash_destroy_chain(void);
|
||||||
|
|
||||||
|
/* This is the old private API, invoked by the macros before 3.9.
|
||||||
|
Kept for binary compatibility of extensions using the stable ABI. */
|
||||||
PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyObject*);
|
PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyObject*);
|
||||||
PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void);
|
PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void);
|
||||||
|
|
||||||
|
/* Forward declarations for PyThreadState */
|
||||||
|
struct _ts;
|
||||||
|
|
||||||
|
/* Python 3.9 private API, invoked by the macros below. */
|
||||||
|
PyAPI_FUNC(int) _PyTrash_begin(struct _ts *tstate, PyObject *op);
|
||||||
|
PyAPI_FUNC(void) _PyTrash_end(struct _ts *tstate);
|
||||||
|
|
||||||
#define PyTrash_UNWIND_LEVEL 50
|
#define PyTrash_UNWIND_LEVEL 50
|
||||||
|
|
||||||
#define Py_TRASHCAN_BEGIN_CONDITION(op, cond) \
|
#define Py_TRASHCAN_BEGIN_CONDITION(op, cond) \
|
||||||
|
@ -520,24 +528,19 @@ PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void);
|
||||||
* is run normally without involving the trashcan */ \
|
* is run normally without involving the trashcan */ \
|
||||||
if (cond) { \
|
if (cond) { \
|
||||||
_tstate = PyThreadState_GET(); \
|
_tstate = PyThreadState_GET(); \
|
||||||
if (_tstate->trash_delete_nesting >= PyTrash_UNWIND_LEVEL) { \
|
if (_PyTrash_begin(_tstate, _PyObject_CAST(op))) { \
|
||||||
/* Store the object (to be deallocated later) and jump past \
|
|
||||||
* Py_TRASHCAN_END, skipping the body of the deallocator */ \
|
|
||||||
_PyTrash_thread_deposit_object(_PyObject_CAST(op)); \
|
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
++_tstate->trash_delete_nesting; \
|
|
||||||
}
|
}
|
||||||
/* The body of the deallocator is here. */
|
/* The body of the deallocator is here. */
|
||||||
#define Py_TRASHCAN_END \
|
#define Py_TRASHCAN_END \
|
||||||
if (_tstate) { \
|
if (_tstate) { \
|
||||||
--_tstate->trash_delete_nesting; \
|
_PyTrash_end(_tstate); \
|
||||||
if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \
|
|
||||||
_PyTrash_thread_destroy_chain(); \
|
|
||||||
} \
|
} \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
#define Py_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_BEGIN_CONDITION(op, \
|
#define Py_TRASHCAN_BEGIN(op, dealloc) \
|
||||||
|
Py_TRASHCAN_BEGIN_CONDITION(op, \
|
||||||
Py_TYPE(op)->tp_dealloc == (destructor)(dealloc))
|
Py_TYPE(op)->tp_dealloc == (destructor)(dealloc))
|
||||||
|
|
||||||
/* For backwards compatibility, these macros enable the trashcan
|
/* For backwards compatibility, these macros enable the trashcan
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Py_TRASHCAN_BEGIN_CONDITION and Py_TRASHCAN_END macro no longer access
|
||||||
|
PyThreadState attributes, but call new private _PyTrash_begin() and
|
||||||
|
_PyTrash_end() functions which hide implementation details.
|
|
@ -2116,6 +2116,30 @@ _PyTrash_thread_destroy_chain(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyTrash_begin(PyThreadState *tstate, PyObject *op)
|
||||||
|
{
|
||||||
|
if (tstate->trash_delete_nesting >= PyTrash_UNWIND_LEVEL) {
|
||||||
|
/* Store the object (to be deallocated later) and jump past
|
||||||
|
* Py_TRASHCAN_END, skipping the body of the deallocator */
|
||||||
|
_PyTrash_thread_deposit_object(op);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
++tstate->trash_delete_nesting;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyTrash_end(PyThreadState *tstate)
|
||||||
|
{
|
||||||
|
--tstate->trash_delete_nesting;
|
||||||
|
if (tstate->trash_delete_later && tstate->trash_delete_nesting <= 0) {
|
||||||
|
_PyTrash_thread_destroy_chain();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _Py_NO_RETURN
|
void _Py_NO_RETURN
|
||||||
_PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg,
|
_PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg,
|
||||||
const char *file, int line, const char *function)
|
const char *file, int line, const char *function)
|
||||||
|
|
Loading…
Reference in a new issue