File indexing completed on 2025-10-31 09:10:44
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 #pragma once
0011 
0012 #include "detail/common.h"
0013 
0014 #include <cassert>
0015 
0016 #if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
0017 #    include "detail/internals.h"
0018 #endif
0019 
0020 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0021 
0022 PYBIND11_NAMESPACE_BEGIN(detail)
0023 
0024 
0025 PyThreadState *get_thread_state_unchecked();
0026 
0027 PYBIND11_NAMESPACE_END(detail)
0028 
0029 #if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
0030 
0031 
0032 
0033 
0034 
0035 
0036 
0037 
0038 
0039 
0040 
0041 
0042 
0043 
0044 
0045 
0046 
0047 
0048 
0049 
0050 
0051 
0052 
0053 class gil_scoped_acquire {
0054 public:
0055     PYBIND11_NOINLINE gil_scoped_acquire() {
0056         auto &internals = detail::get_internals();
0057         tstate = (PyThreadState *) PYBIND11_TLS_GET_VALUE(internals.tstate);
0058 
0059         if (!tstate) {
0060             
0061 
0062 
0063 
0064 
0065             tstate = PyGILState_GetThisThreadState();
0066         }
0067 
0068         if (!tstate) {
0069             tstate = PyThreadState_New(internals.istate);
0070 #    if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
0071             if (!tstate) {
0072                 pybind11_fail("scoped_acquire: could not create thread state!");
0073             }
0074 #    endif
0075             tstate->gilstate_counter = 0;
0076             PYBIND11_TLS_REPLACE_VALUE(internals.tstate, tstate);
0077         } else {
0078             release = detail::get_thread_state_unchecked() != tstate;
0079         }
0080 
0081         if (release) {
0082             PyEval_AcquireThread(tstate);
0083         }
0084 
0085         inc_ref();
0086     }
0087 
0088     gil_scoped_acquire(const gil_scoped_acquire &) = delete;
0089     gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
0090 
0091     void inc_ref() { ++tstate->gilstate_counter; }
0092 
0093     PYBIND11_NOINLINE void dec_ref() {
0094         --tstate->gilstate_counter;
0095 #    if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
0096         if (detail::get_thread_state_unchecked() != tstate) {
0097             pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!");
0098         }
0099         if (tstate->gilstate_counter < 0) {
0100             pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!");
0101         }
0102 #    endif
0103         if (tstate->gilstate_counter == 0) {
0104 #    if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
0105             if (!release) {
0106                 pybind11_fail("scoped_acquire::dec_ref(): internal error!");
0107             }
0108 #    endif
0109             PyThreadState_Clear(tstate);
0110             if (active) {
0111                 PyThreadState_DeleteCurrent();
0112             }
0113             PYBIND11_TLS_DELETE_VALUE(detail::get_internals().tstate);
0114             release = false;
0115         }
0116     }
0117 
0118     
0119     
0120     
0121     
0122     
0123     PYBIND11_NOINLINE void disarm() { active = false; }
0124 
0125     PYBIND11_NOINLINE ~gil_scoped_acquire() {
0126         dec_ref();
0127         if (release) {
0128             PyEval_SaveThread();
0129         }
0130     }
0131 
0132 private:
0133     PyThreadState *tstate = nullptr;
0134     bool release = true;
0135     bool active = true;
0136 };
0137 
0138 class gil_scoped_release {
0139 public:
0140     
0141     explicit gil_scoped_release(bool disassoc = false) : disassoc(disassoc) {
0142         assert(PyGILState_Check());
0143         
0144         
0145         
0146         auto &internals = detail::get_internals();
0147         
0148         tstate = PyEval_SaveThread();
0149         if (disassoc) {
0150             
0151             
0152             auto key = internals.tstate;
0153             PYBIND11_TLS_DELETE_VALUE(key);
0154         }
0155     }
0156 
0157     gil_scoped_release(const gil_scoped_release &) = delete;
0158     gil_scoped_release &operator=(const gil_scoped_release &) = delete;
0159 
0160     
0161     
0162     
0163     
0164     
0165     PYBIND11_NOINLINE void disarm() { active = false; }
0166 
0167     ~gil_scoped_release() {
0168         if (!tstate) {
0169             return;
0170         }
0171         
0172         if (active) {
0173             PyEval_RestoreThread(tstate);
0174         }
0175         if (disassoc) {
0176             
0177             
0178             auto key = detail::get_internals().tstate;
0179             PYBIND11_TLS_REPLACE_VALUE(key, tstate);
0180         }
0181     }
0182 
0183 private:
0184     PyThreadState *tstate;
0185     bool disassoc;
0186     bool active = true;
0187 };
0188 
0189 #else 
0190 
0191 class gil_scoped_acquire {
0192     PyGILState_STATE state;
0193 
0194 public:
0195     gil_scoped_acquire() : state{PyGILState_Ensure()} {}
0196     gil_scoped_acquire(const gil_scoped_acquire &) = delete;
0197     gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
0198     ~gil_scoped_acquire() { PyGILState_Release(state); }
0199     void disarm() {}
0200 };
0201 
0202 class gil_scoped_release {
0203     PyThreadState *state;
0204 
0205 public:
0206     
0207     gil_scoped_release() {
0208         assert(PyGILState_Check());
0209         state = PyEval_SaveThread();
0210     }
0211     gil_scoped_release(const gil_scoped_release &) = delete;
0212     gil_scoped_release &operator=(const gil_scoped_release &) = delete;
0213     ~gil_scoped_release() { PyEval_RestoreThread(state); }
0214     void disarm() {}
0215 };
0216 
0217 #endif 
0218 
0219 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)