File indexing completed on 2025-01-18 10:17:47
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include "detail/common.h"
0013
0014 #if defined(WITH_THREAD) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
0015 # include "detail/internals.h"
0016 #endif
0017
0018 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0019
0020 PYBIND11_NAMESPACE_BEGIN(detail)
0021
0022
0023 PyThreadState *get_thread_state_unchecked();
0024
0025 PYBIND11_NAMESPACE_END(detail)
0026
0027 #if defined(WITH_THREAD)
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 explicit gil_scoped_release(bool disassoc = false) : disassoc(disassoc) {
0141
0142
0143
0144 auto &internals = detail::get_internals();
0145
0146 tstate = PyEval_SaveThread();
0147 if (disassoc) {
0148
0149
0150 auto key = internals.tstate;
0151 PYBIND11_TLS_DELETE_VALUE(key);
0152 }
0153 }
0154
0155 gil_scoped_release(const gil_scoped_acquire &) = delete;
0156 gil_scoped_release &operator=(const gil_scoped_acquire &) = delete;
0157
0158
0159
0160
0161
0162
0163 PYBIND11_NOINLINE void disarm() { active = false; }
0164
0165 ~gil_scoped_release() {
0166 if (!tstate) {
0167 return;
0168 }
0169
0170 if (active) {
0171 PyEval_RestoreThread(tstate);
0172 }
0173 if (disassoc) {
0174
0175
0176 auto key = detail::get_internals().tstate;
0177 PYBIND11_TLS_REPLACE_VALUE(key, tstate);
0178 }
0179 }
0180
0181 private:
0182 PyThreadState *tstate;
0183 bool disassoc;
0184 bool active = true;
0185 };
0186
0187 # else
0188
0189 class gil_scoped_acquire {
0190 PyGILState_STATE state;
0191
0192 public:
0193 gil_scoped_acquire() : state{PyGILState_Ensure()} {}
0194 gil_scoped_acquire(const gil_scoped_acquire &) = delete;
0195 gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
0196 ~gil_scoped_acquire() { PyGILState_Release(state); }
0197 void disarm() {}
0198 };
0199
0200 class gil_scoped_release {
0201 PyThreadState *state;
0202
0203 public:
0204 gil_scoped_release() : state{PyEval_SaveThread()} {}
0205 gil_scoped_release(const gil_scoped_release &) = delete;
0206 gil_scoped_release &operator=(const gil_scoped_acquire &) = delete;
0207 ~gil_scoped_release() { PyEval_RestoreThread(state); }
0208 void disarm() {}
0209 };
0210
0211 # endif
0212
0213 #else
0214
0215 class gil_scoped_acquire {
0216 public:
0217 gil_scoped_acquire() {
0218
0219 (void) (this != (this + 1));
0220 }
0221 gil_scoped_acquire(const gil_scoped_acquire &) = delete;
0222 gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
0223 void disarm() {}
0224 };
0225
0226 class gil_scoped_release {
0227 public:
0228 gil_scoped_release() {
0229
0230 (void) (this != (this + 1));
0231 }
0232 gil_scoped_release(const gil_scoped_release &) = delete;
0233 gil_scoped_release &operator=(const gil_scoped_acquire &) = delete;
0234 void disarm() {}
0235 };
0236
0237 #endif
0238
0239 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)