1 /*
2     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
3 
4     All rights reserved. Use of this source code is governed by a
5     BSD-style license that can be found in the LICENSE file.
6 */
7 
8 
9 
10 
11 #pragma once
12 
13 #include "../pytypes.h"
14 
15 NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
16 NAMESPACE_BEGIN(detail)
17 
18 inline PyTypeObject *make_static_property_type();
19 inline PyTypeObject *make_default_metaclass();
20 inline PyObject *make_object_base_type(PyTypeObject *metaclass);
21 
22 
23 
24 #if PY_VERSION_HEX >= 0x03070000
25 #    define PYBIND11_TLS_KEY_INIT(var) Py_tss_t *var = nullptr
26 #    define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key))
27 #    define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set((key), (tstate))
28 #    define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set((key), nullptr)
29 #else
30 
31 #    define PYBIND11_TLS_KEY_INIT(var) decltype(PyThread_create_key()) var = 0
32 #    define PYBIND11_TLS_GET_VALUE(key) PyThread_get_key_value((key))
33 #    if PY_MAJOR_VERSION < 3
34 #        define PYBIND11_TLS_DELETE_VALUE(key)                               \
35              PyThread_delete_key_value(key)
36 #        define PYBIND11_TLS_REPLACE_VALUE(key, value)                       \
37              do {                                                            \
38                  PyThread_delete_key_value((key));                           \
39                  PyThread_set_key_value((key), (value));                     \
40              } while (false)
41 #    else
42 #        define PYBIND11_TLS_DELETE_VALUE(key)                               \
43              PyThread_set_key_value((key), nullptr)
44 #        define PYBIND11_TLS_REPLACE_VALUE(key, value)                       \
45              PyThread_set_key_value((key), (value))
46 #    endif
47 #endif
48 
49 
50 
51 
52 
53 
54 
55 #if defined(__GLIBCXX__)
same_type(const std::type_info & lhs,const std::type_info & rhs)56 inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) { return lhs == rhs; }
57 using type_hash = std::hash<std::type_index>;
58 using type_equal_to = std::equal_to<std::type_index>;
59 #else
same_type(const std::type_info & lhs,const std::type_info & rhs)60 inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) {
61     return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0;
62 }
63 
64 struct type_hash {
operatortype_hash65     size_t operator()(const std::type_index &t) const {
66         size_t hash = 5381;
67         const char *ptr = t.name();
68         while (auto c = static_cast<unsigned char>(*ptr++))
69             hash = (hash * 33) ^ c;
70         return hash;
71     }
72 };
73 
74 struct type_equal_to {
operatortype_equal_to75     bool operator()(const std::type_index &lhs, const std::type_index &rhs) const {
76         return lhs.name() == rhs.name() || std::strcmp(lhs.name(), rhs.name()) == 0;
77     }
78 };
79 #endif
80 
81 template <typename value_type>
82 using type_map = std::unordered_map<std::type_index, value_type, type_hash, type_equal_to>;
83 
84 struct overload_hash {
operatoroverload_hash85     inline size_t operator()(const std::pair<const PyObject *, const char *>& v) const {
86         size_t value = std::hash<const void *>()(v.first);
87         value ^= std::hash<const void *>()(v.second)  + 0x9e3779b9 + (value<<6) + (value>>2);
88         return value;
89     }
90 };
91 
92 
93 
94 
95 struct internals {
96     type_map<type_info *> registered_types_cpp;
97     std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py;
98     std::unordered_multimap<const void *, instance*> registered_instances;
99     std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache;
100     type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
101     std::unordered_map<const PyObject *, std::vector<PyObject *>> patients;
102     std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators;
103     std::unordered_map<std::string, void *> shared_data;
104     std::vector<PyObject *> loader_patient_stack;
105     std::forward_list<std::string> static_strings;
106     PyTypeObject *static_property_type;
107     PyTypeObject *default_metaclass;
108     PyObject *instance_base;
109 #if defined(WITH_THREAD)
110     PYBIND11_TLS_KEY_INIT(tstate);
111     PyInterpreterState *istate = nullptr;
112 #endif
113 };
114 
115 
116 
117 struct type_info {
118     PyTypeObject *type;
119     const std::type_info *cpptype;
120     size_t type_size, type_align, holder_size_in_ptrs;
121     void *(*operator_new)(size_t);
122     void (*init_instance)(instance *, const void *);
123     void (*dealloc)(value_and_holder &v_h);
124     std::vector<PyObject *(*)(PyObject *, PyTypeObject *)> implicit_conversions;
125     std::vector<std::pair<const std::type_info *, void *(*)(void *)>> implicit_casts;
126     std::vector<bool (*)(PyObject *, void *&)> *direct_conversions;
127     buffer_info *(*get_buffer)(PyObject *, void *) = nullptr;
128     void *get_buffer_data = nullptr;
129     void *(*module_local_load)(PyObject *, const type_info *) = nullptr;
130 
131     bool simple_type : 1;
132 
133     bool simple_ancestors : 1;
134 
135     bool default_holder : 1;
136 
137     bool module_local : 1;
138 };
139 
140 
141 #define PYBIND11_INTERNALS_VERSION 3
142 
143 #if defined(_DEBUG)
144 #   define PYBIND11_BUILD_TYPE "_debug"
145 #else
146 #   define PYBIND11_BUILD_TYPE ""
147 #endif
148 
149 #if defined(WITH_THREAD)
150 #  define PYBIND11_INTERNALS_KIND ""
151 #else
152 #  define PYBIND11_INTERNALS_KIND "_without_thread"
153 #endif
154 
155 #define PYBIND11_INTERNALS_ID "__pybind11_internals_v" \
156     PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) PYBIND11_INTERNALS_KIND PYBIND11_BUILD_TYPE "__"
157 
158 #define PYBIND11_MODULE_LOCAL_ID "__pybind11_module_local_v" \
159     PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) PYBIND11_INTERNALS_KIND PYBIND11_BUILD_TYPE "__"
160 
161 
162 
get_internals_pp()163 inline internals **&get_internals_pp() {
164     static internals **internals_pp = nullptr;
165     return internals_pp;
166 }
167 
168 
get_internals()169 PYBIND11_NOINLINE inline internals &get_internals() {
170     auto **&internals_pp = get_internals_pp();
171     if (internals_pp && *internals_pp)
172         return **internals_pp;
173 
174     constexpr auto *id = PYBIND11_INTERNALS_ID;
175     auto builtins = handle(PyEval_GetBuiltins());
176     if (builtins.contains(id) && isinstance<capsule>(builtins[id])) {
177         internals_pp = static_cast<internals **>(capsule(builtins[id]));
178 
179 
180 
181 
182 
183 
184 #if !defined(__GLIBCXX__)
185         (*internals_pp)->registered_exception_translators.push_front(
186             [](std::exception_ptr p) -> void {
187                 try {
188                     if (p) std::rethrow_exception(p);
189                 } catch (error_already_set &e)       { e.restore();   return;
190                 } catch (const builtin_exception &e) { e.set_error(); return;
191                 }
192             }
193         );
194 #endif
195     } else {
196         if (!internals_pp) internals_pp = new internals*();
197         auto *&internals_ptr = *internals_pp;
198         internals_ptr = new internals();
199 #if defined(WITH_THREAD)
200         PyEval_InitThreads();
201         PyThreadState *tstate = PyThreadState_Get();
202         #if PY_VERSION_HEX >= 0x03070000
203             internals_ptr->tstate = PyThread_tss_alloc();
204             if (!internals_ptr->tstate || PyThread_tss_create(internals_ptr->tstate))
205                 pybind11_fail("get_internals: could not successfully initialize the TSS key!");
206             PyThread_tss_set(internals_ptr->tstate, tstate);
207         #else
208             internals_ptr->tstate = PyThread_create_key();
209             if (internals_ptr->tstate == -1)
210                 pybind11_fail("get_internals: could not successfully initialize the TLS key!");
211             PyThread_set_key_value(internals_ptr->tstate, tstate);
212         #endif
213         internals_ptr->istate = tstate->interp;
214 #endif
215         builtins[id] = capsule(internals_pp);
216         internals_ptr->registered_exception_translators.push_front(
217             [](std::exception_ptr p) -> void {
218                 try {
219                     if (p) std::rethrow_exception(p);
220                 } catch (error_already_set &e)           { e.restore();                                    return;
221                 } catch (const builtin_exception &e)     { e.set_error();                                  return;
222                 } catch (const std::bad_alloc &e)        { PyErr_SetString(PyExc_MemoryError,   e.what()); return;
223                 } catch (const std::domain_error &e)     { PyErr_SetString(PyExc_ValueError,    e.what()); return;
224                 } catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError,    e.what()); return;
225                 } catch (const std::length_error &e)     { PyErr_SetString(PyExc_ValueError,    e.what()); return;
226                 } catch (const std::out_of_range &e)     { PyErr_SetString(PyExc_IndexError,    e.what()); return;
227                 } catch (const std::range_error &e)      { PyErr_SetString(PyExc_ValueError,    e.what()); return;
228                 } catch (const std::exception &e)        { PyErr_SetString(PyExc_RuntimeError,  e.what()); return;
229                 } catch (...) {
230                     PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
231                     return;
232                 }
233             }
234         );
235         internals_ptr->static_property_type = make_static_property_type();
236         internals_ptr->default_metaclass = make_default_metaclass();
237         internals_ptr->instance_base = make_object_base_type(internals_ptr->default_metaclass);
238     }
239     return **internals_pp;
240 }
241 
242 
registered_local_types_cpp()243 inline type_map<type_info *> &registered_local_types_cpp() {
244     static type_map<type_info *> locals{};
245     return locals;
246 }
247 
248 
249 
250 
251 
252 template <typename... Args>
c_str(Args &&...args)253 const char *c_str(Args &&...args) {
254     auto &strings = get_internals().static_strings;
255     strings.emplace_front(std::forward<Args>(args)...);
256     return strings.front().c_str();
257 }
258 
NAMESPACE_END(detail)259 NAMESPACE_END(detail)
260 
261 
262 
263 
264 inline PYBIND11_NOINLINE void *get_shared_data(const std::string &name) {
265     auto &internals = detail::get_internals();
266     auto it = internals.shared_data.find(name);
267     return it != internals.shared_data.end() ? it->second : nullptr;
268 }
269 
270 
set_shared_data(const std::string & name,void * data)271 inline PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *data) {
272     detail::get_internals().shared_data[name] = data;
273     return data;
274 }
275 
276 
277 
278 
279 template<typename T>
get_or_create_shared_data(const std::string & name)280 T &get_or_create_shared_data(const std::string &name) {
281     auto &internals = detail::get_internals();
282     auto it = internals.shared_data.find(name);
283     T *ptr = (T *) (it != internals.shared_data.end() ? it->second : nullptr);
284     if (!ptr) {
285         ptr = new T();
286         internals.shared_data[name] = ptr;
287     }
288     return *ptr;
289 }
290 
291 NAMESPACE_END(PYBIND11_NAMESPACE)
292