| 242 | |
| 243 | template <template <typename...> typename SmartPtr, typename... Ts> |
| 244 | class SmartPtrNoGIL : public SmartPtr<Ts...> { |
| 245 | using Base = SmartPtr<Ts...>; |
| 246 | |
| 247 | public: |
| 248 | template <typename... Args> |
| 249 | SmartPtrNoGIL(Args&&... args) : Base(std::forward<Args>(args)...) {} |
| 250 | |
| 251 | ~SmartPtrNoGIL() { reset(); } |
| 252 | |
| 253 | template <typename... Args> |
| 254 | void reset(Args&&... args) { |
| 255 | auto release_guard = optional_gil_release(); |
| 256 | Base::reset(std::forward<Args>(args)...); |
| 257 | } |
| 258 | |
| 259 | template <typename V> |
| 260 | SmartPtrNoGIL& operator=(V&& v) { |
| 261 | auto release_guard = optional_gil_release(); |
| 262 | Base::operator=(std::forward<V>(v)); |
| 263 | return *this; |
| 264 | } |
| 265 | |
| 266 | private: |
| 267 | // Only release the GIL if we own an object *and* the Python runtime is |
| 268 | // valid *and* the GIL is held. |
| 269 | std::optional<PyReleaseGIL> optional_gil_release() const { |
| 270 | if (this->get() != nullptr && Py_IsInitialized() && PyGILState_Check()) { |
| 271 | return PyReleaseGIL(); |
| 272 | } |
| 273 | return {}; |
| 274 | } |
| 275 | }; |
| 276 | |
| 277 | /// \brief A std::shared_ptr<T, ...> subclass that releases the GIL when destroying T |
| 278 | template <typename... Ts> |
nothing calls this directly
no test coverage detected