File indexing completed on 2025-01-18 10:06:14
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)