cannot fail.
.. versionadded:: 3.14
+
+.. c:function:: int PyUnstable_SetImmortal(PyObject *op)
+
+ Marks the object *op* :term:`immortal`. The argument should be uniquely referenced by
+ the calling thread. This is intended to be used for reducing reference counting contention
+ in the :term:`free-threaded build` for objects which are shared across threads.
+
+ This is a one-way process: objects can only be made immortal; they cannot be
+ made mortal once again. Immortal objects do not participate in reference counting
+ and will never be garbage collected. If the object is GC-tracked, it is untracked.
+
+ This function is intended to be used soon after *op* is created, by the code that
+ creates it, such as in the object's :c:member:`~PyTypeObject.tp_new` slot.
+ Returns 1 if the object was made immortal and returns 0 if it was not.
+ This function cannot fail.
+
+ .. versionadded:: next
Py_RETURN_NONE;
}
+static PyObject *
+test_py_set_immortal(PyObject *self, PyObject *unused)
+{
+ // the object is allocated on C stack as otherwise,
+ // it would trip the refleak checker when the object
+ // is made immortal and leak memory, for the same
+ // reason we cannot call PyObject_Init() on it.
+ PyObject object = {0};
+#ifdef Py_GIL_DISABLED
+ object.ob_tid = _Py_ThreadId();
+ object.ob_gc_bits = 0;
+ object.ob_ref_local = 1;
+ object.ob_ref_shared = 0;
+#else
+ object.ob_refcnt = 1;
+#endif
+ object.ob_type = &PyBaseObject_Type;
+
+ assert(!PyUnstable_IsImmortal(&object));
+ int rc = PyUnstable_SetImmortal(&object);
+ assert(rc == 1);
+ assert(PyUnstable_IsImmortal(&object));
+ Py_DECREF(&object); // should not dealloc
+ assert(PyUnstable_IsImmortal(&object));
+
+ // Check already immortal object
+ rc = PyUnstable_SetImmortal(&object);
+ assert(rc == 0);
+
+ // Check unicode objects
+ PyObject *unicode = PyUnicode_FromString("test");
+ assert(!PyUnstable_IsImmortal(unicode));
+ rc = PyUnstable_SetImmortal(unicode);
+ assert(rc == 0);
+ assert(!PyUnstable_IsImmortal(unicode));
+ Py_DECREF(unicode);
+ Py_RETURN_NONE;
+}
static PyObject *
_test_incref(PyObject *ob)
{"pyobject_is_unique_temporary", pyobject_is_unique_temporary, METH_O},
{"pyobject_is_unique_temporary_new_object", pyobject_is_unique_temporary_new_object, METH_NOARGS},
{"test_py_try_inc_ref", test_py_try_inc_ref, METH_NOARGS},
+ {"test_py_set_immortal", test_py_set_immortal, METH_NOARGS},
{"test_xincref_doesnt_leak",test_xincref_doesnt_leak, METH_NOARGS},
{"test_incref_doesnt_leak", test_incref_doesnt_leak, METH_NOARGS},
{"test_xdecref_doesnt_leak",test_xdecref_doesnt_leak, METH_NOARGS},