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