]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39947: Hide implementation detail of trashcan macros (GH-18971)
authorVictor Stinner <vstinner@python.org>
Fri, 13 Mar 2020 15:51:52 +0000 (16:51 +0100)
committerGitHub <noreply@github.com>
Fri, 13 Mar 2020 15:51:52 +0000 (16:51 +0100)
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.

Include/cpython/object.h
Misc/NEWS.d/next/C API/2020-03-12-23-47-57.bpo-39947.-nCdFV.rst [new file with mode: 0644]
Objects/object.c

index 4600f942ee7669c225a38ed0f1ebb4bfbfdd0fa8..45da752ed2e941b4f0c52815760355787fd648ae 100644 (file)
@@ -385,11 +385,6 @@ PyAPI_DATA(PyTypeObject) _PyNotImplemented_Type;
  */
 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)
 _PyDebugAllocatorStats(FILE *out, const char *block_name, int num_blocks,
                        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().
 */
 
-/* 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_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 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 */ \
         if (cond) { \
             _tstate = PyThreadState_GET(); \
-            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(_PyObject_CAST(op)); \
+            if (_PyTrash_begin(_tstate, _PyObject_CAST(op))) { \
                 break; \
             } \
-            ++_tstate->trash_delete_nesting; \
         }
         /* The body of the deallocator is here. */
 #define Py_TRASHCAN_END \
         if (_tstate) { \
-            --_tstate->trash_delete_nesting; \
-            if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \
-                _PyTrash_thread_destroy_chain(); \
+            _PyTrash_end(_tstate); \
         } \
     } 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))
 
 /* For backwards compatibility, these macros enable the trashcan
diff --git a/Misc/NEWS.d/next/C API/2020-03-12-23-47-57.bpo-39947.-nCdFV.rst b/Misc/NEWS.d/next/C API/2020-03-12-23-47-57.bpo-39947.-nCdFV.rst
new file mode 100644 (file)
index 0000000..559d3dc
--- /dev/null
@@ -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.
index 72c4189d3458cd7dcd32b74b5017f0457528942b..e6d0da1c775c261f4bd9a10ac1e9bfe49ab5a1e7 100644 (file)
@@ -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
 _PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg,
                        const char *file, int line, const char *function)