Skip to content

Commit

Permalink
fix: make gil_safe_call_once thread-safe in free-threaded CPython (#5246
Browse files Browse the repository at this point in the history
)

* fix: Make gil_safe_call_once thread-safe in free-threaded CPython

The "is_initialized_" flags is not protected by the GIL in free-threaded
Python, so it needs to be an atomic field.

Fixes #5245

* style: pre-commit fixes

* Apply changes from code review

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
2 people authored and henryiii committed Aug 13, 2024
1 parent d699e99 commit f3a6d41
Showing 1 changed file with 10 additions and 1 deletion.
11 changes: 10 additions & 1 deletion include/pybind11/gil_safe_call_once.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include <cassert>
#include <mutex>

#ifdef Py_GIL_DISABLED
# include <atomic>
#endif

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

// Use the `gil_safe_call_once_and_store` class below instead of the naive
Expand Down Expand Up @@ -82,7 +86,12 @@ class gil_safe_call_once_and_store {
private:
alignas(T) char storage_[sizeof(T)] = {};
std::once_flag once_flag_ = {};
bool is_initialized_ = false;
#ifdef Py_GIL_DISABLED
std::atomic_bool
#else
bool
#endif
is_initialized_{false};
// The `is_initialized_`-`storage_` pair is very similar to `std::optional`,
// but the latter does not have the triviality properties of former,
// therefore `std::optional` is not a viable alternative here.
Expand Down

0 comments on commit f3a6d41

Please sign in to comment.