mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-28 16:11:59 +00:00
LazyInitializeAtLeastOnceDestroyNever v1
This commit is contained in:
parent
6c77208561
commit
38317c3139
@ -14,12 +14,14 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdalign.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
@ -42,6 +44,30 @@ class array; // Forward declaration
|
|||||||
|
|
||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
// Main author of this class: jbms@
|
||||||
|
template <typename T>
|
||||||
|
class LazyInitializeAtLeastOnceDestroyNever {
|
||||||
|
public:
|
||||||
|
template <typename Initialize>
|
||||||
|
T &Get(Initialize &&initialize) {
|
||||||
|
if (!initialized_) {
|
||||||
|
assert(PyGILState_Check());
|
||||||
|
// Multiple threads may run this concurrently, but that is fine.
|
||||||
|
auto value = initialize(); // May release and re-acquire the GIL.
|
||||||
|
if (!initialized_) { // This runs with the GIL held,
|
||||||
|
new // therefore this is reached only once.
|
||||||
|
(reinterpret_cast<T *>(value_storage_)) T(std::move(value));
|
||||||
|
initialized_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *reinterpret_cast<T *>(value_storage_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
alignas(T) char value_storage_[sizeof(T)];
|
||||||
|
bool initialized_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct handle_type_name<array> {
|
struct handle_type_name<array> {
|
||||||
static constexpr auto name = const_name("numpy.ndarray");
|
static constexpr auto name = const_name("numpy.ndarray");
|
||||||
@ -206,8 +232,8 @@ struct npy_api {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static npy_api &get() {
|
static npy_api &get() {
|
||||||
static npy_api api = lookup();
|
static LazyInitializeAtLeastOnceDestroyNever<npy_api> api_init;
|
||||||
return api;
|
return api_init.Get(lookup);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PyArray_Check_(PyObject *obj) const {
|
bool PyArray_Check_(PyObject *obj) const {
|
||||||
@ -643,10 +669,11 @@ public:
|
|||||||
char flags() const { return detail::array_descriptor_proxy(m_ptr)->flags; }
|
char flags() const { return detail::array_descriptor_proxy(m_ptr)->flags; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static object _dtype_from_pep3118() {
|
static object &_dtype_from_pep3118() {
|
||||||
module_ m = detail::import_numpy_core_submodule("_internal");
|
static detail::LazyInitializeAtLeastOnceDestroyNever<object> imported_obj;
|
||||||
static PyObject *obj = m.attr("_dtype_from_pep3118").cast<object>().release().ptr();
|
return imported_obj.Get([]() {
|
||||||
return reinterpret_borrow<object>(obj);
|
return detail::import_numpy_core_submodule("_internal").attr("_dtype_from_pep3118");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
dtype strip_padding(ssize_t itemsize) {
|
dtype strip_padding(ssize_t itemsize) {
|
||||||
|
Loading…
Reference in New Issue
Block a user