Warning, file /include/pybind11/detail/internals.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include <pybind11/conduit/pybind11_platform_abi_id.h>
0013 #include <pybind11/gil_simple.h>
0014 #include <pybind11/pytypes.h>
0015 #include <pybind11/trampoline_self_life_support.h>
0016
0017 #include "common.h"
0018 #include "struct_smart_holder.h"
0019
0020 #include <atomic>
0021 #include <cstdint>
0022 #include <exception>
0023 #include <limits>
0024 #include <mutex>
0025 #include <thread>
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 #ifndef PYBIND11_INTERNALS_VERSION
0042 # define PYBIND11_INTERNALS_VERSION 11
0043 #endif
0044
0045 #if PYBIND11_INTERNALS_VERSION < 11
0046 # error "PYBIND11_INTERNALS_VERSION 11 is the minimum for all platforms for pybind11v3."
0047 #endif
0048
0049 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0050
0051 using ExceptionTranslator = void (*)(std::exception_ptr);
0052
0053
0054
0055
0056
0057 #define PYBIND11_TLS_KEY_REF Py_tss_t &
0058 #if defined(__clang__)
0059 # define PYBIND11_TLS_KEY_INIT(var) \
0060 _Pragma("clang diagnostic push") \
0061 _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") \
0062 Py_tss_t var \
0063 = Py_tss_NEEDS_INIT; \
0064 _Pragma("clang diagnostic pop")
0065 #elif defined(__GNUC__) && !defined(__INTEL_COMPILER)
0066 # define PYBIND11_TLS_KEY_INIT(var) \
0067 _Pragma("GCC diagnostic push") \
0068 _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") \
0069 Py_tss_t var \
0070 = Py_tss_NEEDS_INIT; \
0071 _Pragma("GCC diagnostic pop")
0072 #else
0073 # define PYBIND11_TLS_KEY_INIT(var) Py_tss_t var = Py_tss_NEEDS_INIT;
0074 #endif
0075 #define PYBIND11_TLS_KEY_CREATE(var) (PyThread_tss_create(&(var)) == 0)
0076 #define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get(&(key))
0077 #define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set(&(key), (value))
0078 #define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set(&(key), nullptr)
0079 #define PYBIND11_TLS_FREE(key) PyThread_tss_delete(&(key))
0080
0081
0082
0083 template <typename T>
0084 class thread_specific_storage {
0085 public:
0086 thread_specific_storage() {
0087
0088 if (!PYBIND11_TLS_KEY_CREATE(key_)) {
0089 pybind11_fail(
0090 "thread_specific_storage constructor: could not initialize the TSS key!");
0091 }
0092 }
0093
0094 ~thread_specific_storage() {
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 #ifdef GRAALVM_PYTHON
0106 if (!Py_IsInitialized() || _Py_IsFinalizing()) {
0107 return;
0108 }
0109 #endif
0110 PYBIND11_TLS_FREE(key_);
0111 }
0112
0113 thread_specific_storage(thread_specific_storage const &) = delete;
0114 thread_specific_storage(thread_specific_storage &&) = delete;
0115 thread_specific_storage &operator=(thread_specific_storage const &) = delete;
0116 thread_specific_storage &operator=(thread_specific_storage &&) = delete;
0117
0118 T *get() const { return reinterpret_cast<T *>(PYBIND11_TLS_GET_VALUE(key_)); }
0119
0120 T &operator*() const { return *get(); }
0121 explicit operator T *() const { return get(); }
0122 explicit operator bool() const { return get() != nullptr; }
0123
0124 void set(T *val) { PYBIND11_TLS_REPLACE_VALUE(key_, reinterpret_cast<void *>(val)); }
0125 void reset(T *p = nullptr) { set(p); }
0126 thread_specific_storage &operator=(T *pval) {
0127 set(pval);
0128 return *this;
0129 }
0130
0131 private:
0132 PYBIND11_TLS_KEY_INIT(mutable key_)
0133 };
0134
0135 PYBIND11_NAMESPACE_BEGIN(detail)
0136
0137
0138 #define PYBIND11_DUMMY_MODULE_NAME "pybind11_builtins"
0139
0140
0141 inline PyTypeObject *make_static_property_type();
0142 inline PyTypeObject *make_default_metaclass();
0143 inline PyObject *make_object_base_type(PyTypeObject *metaclass);
0144 inline void translate_exception(std::exception_ptr p);
0145
0146
0147
0148
0149
0150
0151
0152 #if !defined(_LIBCPP_VERSION)
0153 inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) { return lhs == rhs; }
0154 using type_hash = std::hash<std::type_index>;
0155 using type_equal_to = std::equal_to<std::type_index>;
0156 #else
0157 inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) {
0158 return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0;
0159 }
0160
0161 struct type_hash {
0162 size_t operator()(const std::type_index &t) const {
0163 size_t hash = 5381;
0164 const char *ptr = t.name();
0165 while (auto c = static_cast<unsigned char>(*ptr++)) {
0166 hash = (hash * 33) ^ c;
0167 }
0168 return hash;
0169 }
0170 };
0171
0172 struct type_equal_to {
0173 bool operator()(const std::type_index &lhs, const std::type_index &rhs) const {
0174 return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0;
0175 }
0176 };
0177 #endif
0178
0179 template <typename value_type>
0180 using type_map = std::unordered_map<std::type_index, value_type, type_hash, type_equal_to>;
0181
0182 struct override_hash {
0183 inline size_t operator()(const std::pair<const PyObject *, const char *> &v) const {
0184 size_t value = std::hash<const void *>()(v.first);
0185 value ^= std::hash<const void *>()(v.second) + 0x9e3779b9 + (value << 6) + (value >> 2);
0186 return value;
0187 }
0188 };
0189
0190 using instance_map = std::unordered_multimap<const void *, instance *>;
0191
0192 #ifdef Py_GIL_DISABLED
0193
0194 class pymutex {
0195 PyMutex mutex;
0196
0197 public:
0198 pymutex() : mutex({}) {}
0199 void lock() { PyMutex_Lock(&mutex); }
0200 void unlock() { PyMutex_Unlock(&mutex); }
0201 };
0202
0203
0204 struct instance_map_shard {
0205 instance_map registered_instances;
0206 pymutex mutex;
0207
0208 char padding[64 - (sizeof(instance_map) + sizeof(pymutex)) % 64];
0209 };
0210
0211 static_assert(sizeof(instance_map_shard) % 64 == 0,
0212 "instance_map_shard size is not a multiple of 64 bytes");
0213
0214 inline uint64_t round_up_to_next_pow2(uint64_t x) {
0215
0216
0217 x--;
0218 x |= (x >> 1);
0219 x |= (x >> 2);
0220 x |= (x >> 4);
0221 x |= (x >> 8);
0222 x |= (x >> 16);
0223 x |= (x >> 32);
0224 x++;
0225 return x;
0226 }
0227 #endif
0228
0229 class loader_life_support;
0230
0231
0232
0233
0234 struct internals {
0235 #ifdef Py_GIL_DISABLED
0236 pymutex mutex;
0237 pymutex exception_translator_mutex;
0238 #endif
0239
0240 type_map<type_info *> registered_types_cpp;
0241
0242 std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py;
0243 #ifdef Py_GIL_DISABLED
0244 std::unique_ptr<instance_map_shard[]> instance_shards;
0245 size_t instance_shards_mask = 0;
0246 #else
0247 instance_map registered_instances;
0248 #endif
0249 std::unordered_set<std::pair<const PyObject *, const char *>, override_hash>
0250 inactive_override_cache;
0251 type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
0252 std::unordered_map<const PyObject *, std::vector<PyObject *>> patients;
0253 std::forward_list<ExceptionTranslator> registered_exception_translators;
0254 std::unordered_map<std::string, void *> shared_data;
0255
0256 std::forward_list<std::string> static_strings;
0257
0258 PyTypeObject *static_property_type = nullptr;
0259 PyTypeObject *default_metaclass = nullptr;
0260 PyObject *instance_base = nullptr;
0261
0262 thread_specific_storage<PyThreadState> tstate;
0263 thread_specific_storage<loader_life_support> loader_life_support_tls;
0264
0265 PyInterpreterState *istate = nullptr;
0266
0267 type_map<PyObject *> native_enum_type_map;
0268
0269 internals()
0270 : static_property_type(make_static_property_type()),
0271 default_metaclass(make_default_metaclass()) {
0272 PyThreadState *cur_tstate = PyThreadState_Get();
0273 tstate = cur_tstate;
0274
0275 istate = cur_tstate->interp;
0276 registered_exception_translators.push_front(&translate_exception);
0277 #ifdef Py_GIL_DISABLED
0278
0279
0280 auto num_shards = static_cast<std::uint16_t>(
0281 std::min<std::size_t>(round_up_to_next_pow2(2 * std::thread::hardware_concurrency()),
0282 std::numeric_limits<std::uint16_t>::max()));
0283 if (num_shards == 0) {
0284 num_shards = 1;
0285 }
0286 instance_shards.reset(new instance_map_shard[num_shards]);
0287 instance_shards_mask = num_shards - 1;
0288 #endif
0289 }
0290 internals(const internals &other) = delete;
0291 internals(internals &&other) = delete;
0292 internals &operator=(const internals &other) = delete;
0293 internals &operator=(internals &&other) = delete;
0294 ~internals() = default;
0295 };
0296
0297
0298
0299
0300
0301
0302
0303 struct local_internals {
0304 type_map<type_info *> registered_types_cpp;
0305 std::forward_list<ExceptionTranslator> registered_exception_translators;
0306 PyTypeObject *function_record_py_type = nullptr;
0307 };
0308
0309 enum class holder_enum_t : uint8_t {
0310 undefined,
0311 std_unique_ptr,
0312 std_shared_ptr,
0313 smart_holder,
0314 custom_holder,
0315 };
0316
0317
0318
0319 struct type_info {
0320 PyTypeObject *type;
0321 const std::type_info *cpptype;
0322 size_t type_size, type_align, holder_size_in_ptrs;
0323 void *(*operator_new)(size_t);
0324 void (*init_instance)(instance *, const void *);
0325 void (*dealloc)(value_and_holder &v_h);
0326
0327
0328
0329 memory::get_guarded_delete_fn get_memory_guarded_delete = memory::get_guarded_delete;
0330 get_trampoline_self_life_support_fn get_trampoline_self_life_support = nullptr;
0331
0332 std::vector<PyObject *(*) (PyObject *, PyTypeObject *)> implicit_conversions;
0333 std::vector<std::pair<const std::type_info *, void *(*) (void *)>> implicit_casts;
0334 std::vector<bool (*)(PyObject *, void *&)> *direct_conversions;
0335 buffer_info *(*get_buffer)(PyObject *, void *) = nullptr;
0336 void *get_buffer_data = nullptr;
0337 void *(*module_local_load)(PyObject *, const type_info *) = nullptr;
0338 holder_enum_t holder_enum_v = holder_enum_t::undefined;
0339
0340
0341
0342
0343 bool simple_type : 1;
0344
0345 bool simple_ancestors : 1;
0346
0347 bool module_local : 1;
0348 };
0349
0350 #define PYBIND11_INTERNALS_ID \
0351 "__pybind11_internals_v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \
0352 PYBIND11_COMPILER_TYPE_LEADING_UNDERSCORE PYBIND11_PLATFORM_ABI_ID "__"
0353
0354 #define PYBIND11_MODULE_LOCAL_ID \
0355 "__pybind11_module_local_v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \
0356 PYBIND11_COMPILER_TYPE_LEADING_UNDERSCORE PYBIND11_PLATFORM_ABI_ID "__"
0357
0358 inline PyThreadState *get_thread_state_unchecked() {
0359 #if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
0360 return PyThreadState_GET();
0361 #elif PY_VERSION_HEX < 0x030D0000
0362 return _PyThreadState_UncheckedGet();
0363 #else
0364 return PyThreadState_GetUnchecked();
0365 #endif
0366 }
0367
0368
0369
0370 inline std::atomic<int> &get_num_interpreters_seen() {
0371 static std::atomic<int> counter(0);
0372 return counter;
0373 }
0374
0375 template <class T,
0376 enable_if_t<std::is_same<std::nested_exception, remove_cvref_t<T>>::value, int> = 0>
0377 bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
0378 std::exception_ptr nested = exc.nested_ptr();
0379 if (nested != nullptr && nested != p) {
0380 translate_exception(nested);
0381 return true;
0382 }
0383 return false;
0384 }
0385
0386 template <class T,
0387 enable_if_t<!std::is_same<std::nested_exception, remove_cvref_t<T>>::value, int> = 0>
0388 bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
0389 if (const auto *nep = dynamic_cast<const std::nested_exception *>(std::addressof(exc))) {
0390 return handle_nested_exception(*nep, p);
0391 }
0392 return false;
0393 }
0394
0395 inline bool raise_err(PyObject *exc_type, const char *msg) {
0396 if (PyErr_Occurred()) {
0397 raise_from(exc_type, msg);
0398 return true;
0399 }
0400 set_error(exc_type, msg);
0401 return false;
0402 }
0403
0404 inline void translate_exception(std::exception_ptr p) {
0405 if (!p) {
0406 return;
0407 }
0408 try {
0409 std::rethrow_exception(p);
0410 } catch (error_already_set &e) {
0411 handle_nested_exception(e, p);
0412 e.restore();
0413 return;
0414 } catch (const builtin_exception &e) {
0415
0416 if (const auto *nep = dynamic_cast<const std::nested_exception *>(std::addressof(e))) {
0417 handle_nested_exception(*nep, p);
0418 }
0419 e.set_error();
0420 return;
0421 } catch (const std::bad_alloc &e) {
0422 handle_nested_exception(e, p);
0423 raise_err(PyExc_MemoryError, e.what());
0424 return;
0425 } catch (const std::domain_error &e) {
0426 handle_nested_exception(e, p);
0427 raise_err(PyExc_ValueError, e.what());
0428 return;
0429 } catch (const std::invalid_argument &e) {
0430 handle_nested_exception(e, p);
0431 raise_err(PyExc_ValueError, e.what());
0432 return;
0433 } catch (const std::length_error &e) {
0434 handle_nested_exception(e, p);
0435 raise_err(PyExc_ValueError, e.what());
0436 return;
0437 } catch (const std::out_of_range &e) {
0438 handle_nested_exception(e, p);
0439 raise_err(PyExc_IndexError, e.what());
0440 return;
0441 } catch (const std::range_error &e) {
0442 handle_nested_exception(e, p);
0443 raise_err(PyExc_ValueError, e.what());
0444 return;
0445 } catch (const std::overflow_error &e) {
0446 handle_nested_exception(e, p);
0447 raise_err(PyExc_OverflowError, e.what());
0448 return;
0449 } catch (const std::exception &e) {
0450 handle_nested_exception(e, p);
0451 raise_err(PyExc_RuntimeError, e.what());
0452 return;
0453 } catch (const std::nested_exception &e) {
0454 handle_nested_exception(e, p);
0455 raise_err(PyExc_RuntimeError, "Caught an unknown nested exception!");
0456 return;
0457 } catch (...) {
0458 raise_err(PyExc_RuntimeError, "Caught an unknown exception!");
0459 return;
0460 }
0461 }
0462
0463 #if !defined(__GLIBCXX__)
0464 inline void translate_local_exception(std::exception_ptr p) {
0465 try {
0466 if (p) {
0467 std::rethrow_exception(p);
0468 }
0469 } catch (error_already_set &e) {
0470 e.restore();
0471 return;
0472 } catch (const builtin_exception &e) {
0473 e.set_error();
0474 return;
0475 }
0476 }
0477 #endif
0478
0479 inline object get_python_state_dict() {
0480 object state_dict;
0481 #if defined(PYPY_VERSION) || defined(GRAALVM_PYTHON)
0482 state_dict = reinterpret_borrow<object>(PyEval_GetBuiltins());
0483 #else
0484 # if PY_VERSION_HEX < 0x03090000
0485 PyInterpreterState *istate = _PyInterpreterState_Get();
0486 # else
0487 PyInterpreterState *istate = PyInterpreterState_Get();
0488 # endif
0489 if (istate) {
0490 state_dict = reinterpret_borrow<object>(PyInterpreterState_GetDict(istate));
0491 }
0492 #endif
0493 if (!state_dict) {
0494 raise_from(PyExc_SystemError, "pybind11::detail::get_python_state_dict() FAILED");
0495 throw error_already_set();
0496 }
0497 return state_dict;
0498 }
0499
0500 template <typename InternalsType>
0501 class internals_pp_manager {
0502 public:
0503 using on_fetch_function = void(InternalsType *);
0504 internals_pp_manager(char const *id, on_fetch_function *on_fetch)
0505 : holder_id_(id), on_fetch_(on_fetch) {}
0506
0507
0508
0509 std::unique_ptr<InternalsType> *get_pp() {
0510 #ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT
0511 if (get_num_interpreters_seen() > 1) {
0512
0513
0514
0515 auto *tstate = get_thread_state_unchecked();
0516 if (!tstate || tstate->interp != last_istate_.get()) {
0517 gil_scoped_acquire_simple gil;
0518 if (!tstate) {
0519 tstate = get_thread_state_unchecked();
0520 }
0521 last_istate_ = tstate->interp;
0522 internals_tls_p_ = get_or_create_pp_in_state_dict();
0523 }
0524 return internals_tls_p_.get();
0525 }
0526 #endif
0527 if (!internals_singleton_pp_) {
0528 gil_scoped_acquire_simple gil;
0529 internals_singleton_pp_ = get_or_create_pp_in_state_dict();
0530 }
0531 return internals_singleton_pp_;
0532 }
0533
0534
0535 void unref() {
0536 #ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT
0537 if (get_num_interpreters_seen() > 1) {
0538 last_istate_.reset();
0539 internals_tls_p_.reset();
0540 return;
0541 }
0542 #endif
0543 internals_singleton_pp_ = nullptr;
0544 }
0545
0546 void destroy() {
0547 #ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT
0548 if (get_num_interpreters_seen() > 1) {
0549 auto *tstate = get_thread_state_unchecked();
0550
0551 if (!tstate || tstate->interp == last_istate_.get()) {
0552 auto tpp = internals_tls_p_.get();
0553 if (tpp) {
0554 delete tpp;
0555 }
0556 }
0557 unref();
0558 return;
0559 }
0560 #endif
0561 delete internals_singleton_pp_;
0562 unref();
0563 }
0564
0565 private:
0566 std::unique_ptr<InternalsType> *get_or_create_pp_in_state_dict() {
0567 error_scope err_scope;
0568 dict state_dict = get_python_state_dict();
0569 auto internals_obj
0570 = reinterpret_steal<object>(dict_getitemstringref(state_dict.ptr(), holder_id_));
0571 std::unique_ptr<InternalsType> *pp = nullptr;
0572 if (internals_obj) {
0573 void *raw_ptr = PyCapsule_GetPointer(internals_obj.ptr(), nullptr);
0574 if (!raw_ptr) {
0575 raise_from(PyExc_SystemError,
0576 "pybind11::detail::internals_pp_manager::get_pp_from_dict() FAILED");
0577 throw error_already_set();
0578 }
0579 pp = reinterpret_cast<std::unique_ptr<InternalsType> *>(raw_ptr);
0580 if (on_fetch_ && pp) {
0581 on_fetch_(pp->get());
0582 }
0583 } else {
0584 pp = new std::unique_ptr<InternalsType>;
0585
0586 state_dict[holder_id_] = capsule(reinterpret_cast<void *>(pp));
0587 }
0588 return pp;
0589 }
0590
0591 char const *holder_id_ = nullptr;
0592 on_fetch_function *on_fetch_ = nullptr;
0593 #ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT
0594 thread_specific_storage<PyInterpreterState> last_istate_;
0595 thread_specific_storage<std::unique_ptr<InternalsType>> internals_tls_p_;
0596 #endif
0597 std::unique_ptr<InternalsType> *internals_singleton_pp_;
0598 };
0599
0600
0601
0602
0603
0604
0605
0606
0607 #if !defined(__GLIBCXX__)
0608 inline void check_internals_local_exception_translator(internals *internals_ptr) {
0609 if (internals_ptr) {
0610 for (auto et : internals_ptr->registered_exception_translators) {
0611 if (et == &translate_local_exception) {
0612 return;
0613 }
0614 }
0615 internals_ptr->registered_exception_translators.push_front(&translate_local_exception);
0616 }
0617 }
0618 #endif
0619
0620 inline internals_pp_manager<internals> &get_internals_pp_manager() {
0621 #if defined(__GLIBCXX__)
0622 # define ON_FETCH_FN nullptr
0623 #else
0624 # define ON_FETCH_FN &check_internals_local_exception_translator
0625 #endif
0626 static internals_pp_manager<internals> internals_pp_manager(PYBIND11_INTERNALS_ID,
0627 ON_FETCH_FN);
0628 #undef ON_FETCH_FN
0629 return internals_pp_manager;
0630 }
0631
0632
0633 PYBIND11_NOINLINE internals &get_internals() {
0634 auto &ppmgr = get_internals_pp_manager();
0635 auto &internals_ptr = *ppmgr.get_pp();
0636 if (!internals_ptr) {
0637
0638 gil_scoped_acquire_simple gil;
0639 error_scope err_scope;
0640 internals_ptr.reset(new internals());
0641
0642 if (!internals_ptr->instance_base) {
0643
0644
0645 internals_ptr->instance_base = make_object_base_type(internals_ptr->default_metaclass);
0646 }
0647 }
0648 return *internals_ptr;
0649 }
0650
0651 inline internals_pp_manager<local_internals> &get_local_internals_pp_manager() {
0652
0653
0654 static const std::string this_module_idstr
0655 = PYBIND11_MODULE_LOCAL_ID
0656 + std::to_string(reinterpret_cast<uintptr_t>(&this_module_idstr));
0657 static internals_pp_manager<local_internals> local_internals_pp_manager(
0658 this_module_idstr.c_str(), nullptr);
0659 return local_internals_pp_manager;
0660 }
0661
0662
0663 inline local_internals &get_local_internals() {
0664 auto &ppmgr = get_local_internals_pp_manager();
0665 auto &internals_ptr = *ppmgr.get_pp();
0666 if (!internals_ptr) {
0667 internals_ptr.reset(new local_internals());
0668 }
0669 return *internals_ptr;
0670 }
0671
0672 #ifdef Py_GIL_DISABLED
0673 # define PYBIND11_LOCK_INTERNALS(internals) std::unique_lock<pymutex> lock((internals).mutex)
0674 #else
0675 # define PYBIND11_LOCK_INTERNALS(internals)
0676 #endif
0677
0678 template <typename F>
0679 inline auto with_internals(const F &cb) -> decltype(cb(get_internals())) {
0680 auto &internals = get_internals();
0681 PYBIND11_LOCK_INTERNALS(internals);
0682 return cb(internals);
0683 }
0684
0685 template <typename F>
0686 inline auto with_exception_translators(const F &cb)
0687 -> decltype(cb(get_internals().registered_exception_translators,
0688 get_local_internals().registered_exception_translators)) {
0689 auto &internals = get_internals();
0690 #ifdef Py_GIL_DISABLED
0691 std::unique_lock<pymutex> lock((internals).exception_translator_mutex);
0692 #endif
0693 auto &local_internals = get_local_internals();
0694 return cb(internals.registered_exception_translators,
0695 local_internals.registered_exception_translators);
0696 }
0697
0698 inline std::uint64_t mix64(std::uint64_t z) {
0699
0700
0701
0702 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
0703 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
0704 return z ^ (z >> 31);
0705 }
0706
0707 template <typename F>
0708 inline auto with_instance_map(const void *ptr, const F &cb)
0709 -> decltype(cb(std::declval<instance_map &>())) {
0710 auto &internals = get_internals();
0711
0712 #ifdef Py_GIL_DISABLED
0713
0714
0715
0716
0717
0718 auto addr = reinterpret_cast<std::uintptr_t>(ptr);
0719 auto hash = mix64(static_cast<std::uint64_t>(addr >> 20));
0720 auto idx = static_cast<size_t>(hash & internals.instance_shards_mask);
0721
0722 auto &shard = internals.instance_shards[idx];
0723 std::unique_lock<pymutex> lock(shard.mutex);
0724 return cb(shard.registered_instances);
0725 #else
0726 (void) ptr;
0727 return cb(internals.registered_instances);
0728 #endif
0729 }
0730
0731
0732
0733 inline size_t num_registered_instances() {
0734 auto &internals = get_internals();
0735 #ifdef Py_GIL_DISABLED
0736 size_t count = 0;
0737 for (size_t i = 0; i <= internals.instance_shards_mask; ++i) {
0738 auto &shard = internals.instance_shards[i];
0739 std::unique_lock<pymutex> lock(shard.mutex);
0740 count += shard.registered_instances.size();
0741 }
0742 return count;
0743 #else
0744 return internals.registered_instances.size();
0745 #endif
0746 }
0747
0748
0749
0750
0751
0752 template <typename... Args>
0753 const char *c_str(Args &&...args) {
0754
0755
0756 auto &internals = get_internals();
0757 PYBIND11_LOCK_INTERNALS(internals);
0758 auto &strings = internals.static_strings;
0759 strings.emplace_front(std::forward<Args>(args)...);
0760 return strings.front().c_str();
0761 }
0762
0763 PYBIND11_NAMESPACE_END(detail)
0764
0765
0766
0767
0768 PYBIND11_NOINLINE void *get_shared_data(const std::string &name) {
0769 return detail::with_internals([&](detail::internals &internals) {
0770 auto it = internals.shared_data.find(name);
0771 return it != internals.shared_data.end() ? it->second : nullptr;
0772 });
0773 }
0774
0775
0776 PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *data) {
0777 return detail::with_internals([&](detail::internals &internals) {
0778 internals.shared_data[name] = data;
0779 return data;
0780 });
0781 }
0782
0783
0784
0785
0786 template <typename T>
0787 T &get_or_create_shared_data(const std::string &name) {
0788 return *detail::with_internals([&](detail::internals &internals) {
0789 auto it = internals.shared_data.find(name);
0790 T *ptr = (T *) (it != internals.shared_data.end() ? it->second : nullptr);
0791 if (!ptr) {
0792 ptr = new T();
0793 internals.shared_data[name] = ptr;
0794 }
0795 return ptr;
0796 });
0797 }
0798
0799 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)