Add public shared_data API

NumPy internals are stored under "_numpy_internals" key.
This commit is contained in:
Ivan Smirnov 2016-10-31 14:11:10 +00:00
parent c546655dc2
commit 2dbf029705
2 changed files with 35 additions and 10 deletions

View File

@ -323,7 +323,7 @@ struct internals {
std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache; std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache;
std::unordered_map<std::type_index, std::vector<bool (*)(PyObject *, void *&)>> direct_conversions; std::unordered_map<std::type_index, std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators; std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators;
std::unordered_map<std::string, void *> shared_data; std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across extensions
#if defined(WITH_THREAD) #if defined(WITH_THREAD)
decltype(PyThread_create_key()) tstate = 0; // Usually an int but a long on Cygwin64 with Python 3.x decltype(PyThread_create_key()) tstate = 0; // Usually an int but a long on Cygwin64 with Python 3.x
PyInterpreterState *istate = nullptr; PyInterpreterState *istate = nullptr;
@ -428,6 +428,35 @@ inline void ignore_unused(const int *) { }
NAMESPACE_END(detail) NAMESPACE_END(detail)
/// Returns a named pointer that is shared among all extension modules (using the same
/// pybind11 version) running in the current interpreter. Names starting with underscores
/// are reserved for internal usage. Returns `nullptr` if no matching entry was found.
inline PYBIND11_NOINLINE void* get_shared_data(const std::string& name) {
auto& internals = detail::get_internals();
auto it = internals.shared_data.find(name);
return it != internals.shared_data.end() ? it->second : nullptr;
}
/// Set the shared data that can be later recovered by `get_shared_data()`.
inline PYBIND11_NOINLINE void *set_shared_data(const std::string& name, void *data) {
detail::get_internals().shared_data[name] = data;
return data;
}
/// Returns a typed reference to a shared data entry (by using `get_shared_data()`) if
/// such entry exists. Otherwise, a new object of default-constructible type `T` is
/// added to the shared data under the given name and a reference to it is returned.
template<typename T> T& get_or_create_shared_data(const std::string& name) {
auto& internals = detail::get_internals();
auto it = internals.shared_data.find(name);
T* ptr = (T*) (it != internals.shared_data.end() ? it->second : nullptr);
if (!ptr) {
ptr = new T();
internals.shared_data[name] = ptr;
}
return *ptr;
}
/// Fetch and hold an error which was already set in Python /// Fetch and hold an error which was already set in Python
class error_already_set : public std::runtime_error { class error_already_set : public std::runtime_error {
public: public:

View File

@ -91,18 +91,14 @@ struct numpy_internals {
} }
}; };
inline PYBIND11_NOINLINE numpy_internals* load_numpy_internals() { inline PYBIND11_NOINLINE void load_numpy_internals(numpy_internals* &ptr) {
auto& shared_data = detail::get_internals().shared_data; ptr = &get_or_create_shared_data<numpy_internals>("_numpy_internals");
auto it = shared_data.find("numpy_internals");
if (it != shared_data.end())
return (numpy_internals *)it->second;
auto ptr = new numpy_internals();
shared_data["numpy_internals"] = ptr;
return ptr;
} }
inline numpy_internals& get_numpy_internals() { inline numpy_internals& get_numpy_internals() {
static numpy_internals* ptr = load_numpy_internals(); static numpy_internals* ptr = nullptr;
if (!ptr)
load_numpy_internals(ptr);
return *ptr; return *ptr;
} }