From 1aed3ab1b4682ab61cd41a00284d5a6f1b63e1d1 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 16 Dec 2025 16:33:14 +0800 Subject: [PATCH] Update comments --- include/pybind11/detail/internals.h | 9 +++++++-- include/pybind11/gil_safe_call_once.h | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index c157bf53c..4ff904607 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -627,19 +627,23 @@ public: /// Get the pointer-to-pointer for the main interpreter, allocating it if it does not already /// exist. May acquire the GIL. Will never return nullptr. std::unique_ptr *get_pp_for_main_interpreter() { - // This function **assumes** that the current thread is running in the main interpreter. if (!seen_main_interpreter_) { + // The first call to this function **MUST** be from the main interpreter. + // Here we **ASSUME** that the current thread is running in the main interpreter. + // The caller is responsible for ensuring this. std::call_once(seen_main_interpreter_flag_, [&] { gil_scoped_acquire_simple gil; internals_singleton_pp_ = get_or_create_pp_in_state_dict(); seen_main_interpreter_ = true; }); } + // This is shared between all threads and all interpreters. return internals_singleton_pp_; } /// Drop all the references we're currently holding. void unref() { + // See comment in get_pp() above. #ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT if (get_num_interpreters_seen() > 1) { last_istate_tls() = nullptr; @@ -651,6 +655,7 @@ public: } void destroy() { + // See comment in get_pp() above. #ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT if (get_num_interpreters_seen() > 1) { auto *tstate = get_thread_state_unchecked(); @@ -711,8 +716,8 @@ private: char const *holder_id_ = nullptr; on_fetch_function *on_fetch_ = nullptr; + // Pointer to the singleton internals for the main interpreter std::unique_ptr *internals_singleton_pp_; - std::once_flag seen_main_interpreter_flag_; std::atomic_bool seen_main_interpreter_{false}; }; diff --git a/include/pybind11/gil_safe_call_once.h b/include/pybind11/gil_safe_call_once.h index e00bbb9f0..68314c6f8 100644 --- a/include/pybind11/gil_safe_call_once.h +++ b/include/pybind11/gil_safe_call_once.h @@ -130,7 +130,7 @@ public: // CPython API calls in the `fn()` call below may release and reacquire the GIL. gil_scoped_release gil_rel; // Needed to establish lock ordering. detail::with_internals([&](detail::internals &internals) { - const void *key = reinterpret_cast(this); + const void *const key = reinterpret_cast(this); auto &storage_map = internals.call_once_storage_map; // There can be multiple threads going through here. detail::call_once_storage *value = nullptr; @@ -168,7 +168,7 @@ public: T *result = last_storage_ptr_; if (!is_last_storage_valid()) { detail::with_internals([&](detail::internals &internals) { - const void *key = reinterpret_cast(this); + const void *const key = reinterpret_cast(this); auto &storage_map = internals.call_once_storage_map; auto *value = static_cast *>(storage_map.at(key)); result = last_storage_ptr_ = reinterpret_cast(value->storage);