mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 13:15:12 +00:00
Replace comments:
Document PRECONDITION. Adopt comment suggested by @tkoeppe: https://github.com/pybind/pybind11/pull/4877#discussion_r1350356093
This commit is contained in:
parent
88cec1152a
commit
1ce27154d6
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user