| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2195,3 +2195,100 @@ The C-API provides a basic mutual exclusion lock. | |||
| 2195 | 2195 | issue a fatal error. | |
| 2196 | 2196 | ||
| 2197 | 2197 | .. versionadded:: 3.13 | |
| 2198 | + | ||
| 2199 | + Python Critical Section API | ||
| 2200 | + --------------------------- | ||
| 2201 | + | ||
| 2202 | + The critical section API provides a deadlock avoidance layer on top of | ||
| 2203 | + per-object locks for :term:`free-threaded <free threading>` CPython. They are | ||
| 2204 | + intended to replace reliance on the :term:`global interpreter lock`, and are | ||
| 2205 | + no-ops in versions of Python with the global interpreter lock. | ||
| 2206 | + | ||
| 2207 | + Critical sections avoid deadlocks by implicitly suspending active critical | ||
| 2208 | + sections and releasing the locks during calls to :c:func:`PyEval_SaveThread`. | ||
| 2209 | + When :c:func:`PyEval_RestoreThread` is called, the most recent critical section | ||
| 2210 | + is resumed, and its locks reacquired. This means the critical section API | ||
| 2211 | + provides weaker guarantees than traditional locks -- they are useful because | ||
| 2212 | + their behavior is similar to the :term:`GIL`. | ||
| 2213 | + | ||
| 2214 | + .. note:: | ||
| 2215 | + | ||
| 2216 | + Operations that need to lock two objects at once must use | ||
| 2217 | + :c:macro:`Py_BEGIN_CRITICAL_SECTION2()`. You *cannot* use nested critical | ||
| 2218 | + sections to lock more than one object at once, because the inner critical | ||
| 2219 | + section may suspend the outer critical sections. This API does not provide | ||
| 2220 | + a way to lock more than two objects at once. | ||
| 2221 | + | ||
| 2222 | + Example usage:: | ||
| 2223 | + | ||
| 2224 | + static PyObject * | ||
| 2225 | + set_field(MyObject *self, PyObject *value) | ||
| 2226 | + { | ||
| 2227 | + Py_BEGIN_CRITICAL_SECTION(self); | ||
| 2228 | + Py_SETREF(self->field, value); | ||
| 2229 | + Py_END_CRITICAL_SECTION(); | ||
| 2230 | + Py_RETURN_NONE; | ||
| 2231 | + } | ||
| 2232 | + | ||
| 2233 | + In the above example, :c:macro:`Py_SETREF` calls :c:macro:`Py_DECREF`, which | ||
| 2234 | + can call arbitrary code through an object's deallocation function. The critical | ||
| 2235 | + section API avoids potentital deadlocks due to reentrancy and lock ordering | ||
| 2236 | + by allowing the runtime to temporarily suspend the critical section if the | ||
| 2237 | + code triggered by the finalizer blocks and calls :c:func:`PyEval_SaveThread`. | ||
| 2238 | + | ||
| 2239 | + .. c:macro:: Py_BEGIN_CRITICAL_SECTION(op) | ||
| 2240 | + | ||
| 2241 | + Acquires the per-object lock for the object *op* and begins a | ||
| 2242 | + critical section. | ||
| 2243 | + | ||
| 2244 | + In the free-threaded build, this macro expands to:: | ||
| 2245 | + | ||
| 2246 | + { | ||
| 2247 | + PyCriticalSection _py_cs; | ||
| 2248 | + PyCriticalSection_Begin(&_py_cs, _PyObject_CAST(op)) | ||
| 2249 | + | ||
| 2250 | + In the default build, this macro expands to ``{``. | ||
| 2251 | + | ||
| 2252 | + .. versionadded:: 3.13 | ||
| 2253 | + | ||
| 2254 | + .. c:macro:: Py_END_CRITICAL_SECTION() | ||
| 2255 | + | ||
| 2256 | + Ends the critical section and releases the per-object lock. | ||
| 2257 | + | ||
| 2258 | + In the free-threaded build, this macro expands to:: | ||
| 2259 | + | ||
| 2260 | + PyCriticalSection_End(&_py_cs); | ||
| 2261 | + } | ||
| 2262 | + | ||
| 2263 | + In the default build, this macro expands to ``}``. | ||
| 2264 | + | ||
| 2265 | + .. versionadded:: 3.13 | ||
| 2266 | + | ||
| 2267 | + .. c:macro:: Py_BEGIN_CRITICAL_SECTION2(a, b) | ||
| 2268 | + | ||
| 2269 | + Acquires the per-objects locks for the objects *a* and *b* and begins a | ||
| 2270 | + critical section. The locks are acquired in a consistent order (lowest | ||
| 2271 | + address first) to avoid lock ordering deadlocks. | ||
| 2272 | + | ||
| 2273 | + In the free-threaded build, this macro expands to:: | ||
| 2274 | + | ||
| 2275 | + { | ||
| 2276 | + PyCriticalSection2 _py_cs2; | ||
| 2277 | + PyCriticalSection_Begin2(&_py_cs2, _PyObject_CAST(a), _PyObject_CAST(b)) | ||
| 2278 | + | ||
| 2279 | + In the default build, this macro expands to ``{``. | ||
| 2280 | + | ||
| 2281 | + .. versionadded:: 3.13 | ||
| 2282 | + | ||
| 2283 | + .. c:macro:: Py_END_CRITICAL_SECTION2() | ||
| 2284 | + | ||
| 2285 | + Ends the critical section and releases the per-object locks. | ||
| 2286 | + | ||
| 2287 | + In the free-threaded build, this macro expands to:: | ||
| 2288 | + | ||
| 2289 | + PyCriticalSection_End2(&_py_cs2); | ||
| 2290 | + } | ||
| 2291 | + | ||
| 2292 | + In the default build, this macro expands to ``}``. | ||
| 2293 | + | ||
| 2294 | + .. versionadded:: 3.13 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments