Replace comments:

Document PRECONDITION.

Adopt comment suggested by @tkoeppe: https://github.com/pybind/pybind11/pull/4877#discussion_r1350356093
This commit is contained in:
Ralf W. Grosse-Kunstleve 2023-10-09 07:24:17 -07:00
parent 88cec1152a
commit 1ce27154d6

View File

@ -47,15 +47,18 @@ PYBIND11_NAMESPACE_BEGIN(detail)
template <typename T> template <typename T>
class LazyInitializeAtLeastOnceDestroyNever { class LazyInitializeAtLeastOnceDestroyNever {
public: public:
// PRECONDITION: The GIL must be held when `Get()` is called.
// It is possible that multiple threads execute `Get()` with `initialized_`
// still being false, and thus proceed to execute `initialize()`. This can
// happen if `initialize()` releases and reacquires the GIL internally.
// We accept this, and expect the operation to be both idempotent and cheap.
template <typename Initialize> template <typename Initialize>
T &Get(Initialize &&initialize) { T &Get(Initialize &&initialize) {
if (!initialized_) { if (!initialized_) {
assert(PyGILState_Check()); assert(PyGILState_Check());
// Multiple threads may run this concurrently, but that is fine. auto value = initialize();
auto value = initialize(); // May release and re-acquire the GIL. if (!initialized_) {
if (!initialized_) { // This runs with the GIL held, new (reinterpret_cast<T *>(value_storage_)) T(std::move(value));
new // therefore this is reached only once.
(reinterpret_cast<T *>(value_storage_)) T(std::move(value));
initialized_ = true; initialized_ = true;
} }
} }