diff options
Diffstat (limited to '3rdparty/pybind11/tests/constructor_stats.h')
-rw-r--r-- | 3rdparty/pybind11/tests/constructor_stats.h | 143 |
1 files changed, 95 insertions, 48 deletions
diff --git a/3rdparty/pybind11/tests/constructor_stats.h b/3rdparty/pybind11/tests/constructor_stats.h index 805968a0..937f6c23 100644 --- a/3rdparty/pybind11/tests/constructor_stats.h +++ b/3rdparty/pybind11/tests/constructor_stats.h @@ -56,7 +56,8 @@ from the ConstructorStats instance `.values()` method. In some cases, when you need to track instances of a C++ class not registered with pybind11, you need to add a function returning the ConstructorStats for the C++ class; this can be done with: - m.def("get_special_cstats", &ConstructorStats::get<SpecialClass>, py::return_value_policy::reference) + m.def("get_special_cstats", &ConstructorStats::get<SpecialClass>, +py::return_value_policy::reference) Finally, you can suppress the output messages, but keep the constructor tracking (for inspection/testing in python) by using the functions with `print_` replaced with `track_` (e.g. @@ -65,15 +66,18 @@ inspection/testing in python) by using the functions with `print_` replaced with */ #include "pybind11_tests.h" -#include <unordered_map> + #include <list> -#include <typeindex> #include <sstream> +#include <typeindex> +#include <unordered_map> class ConstructorStats { protected: - std::unordered_map<void*, int> _instances; // Need a map rather than set because members can shared address with parents - std::list<std::string> _values; // Used to track values (e.g. of value constructors) + std::unordered_map<void *, int> _instances; // Need a map rather than set because members can + // shared address with parents + std::list<std::string> _values; // Used to track values + // (e.g. of value constructors) public: int default_constructions = 0; int copy_constructions = 0; @@ -96,26 +100,26 @@ public: default_constructions++; } - void created(void *inst) { - ++_instances[inst]; - } + void created(void *inst) { ++_instances[inst]; } void destroyed(void *inst) { - if (--_instances[inst] < 0) + if (--_instances[inst] < 0) { throw std::runtime_error("cstats.destroyed() called with unknown " "instance; potential double-destruction " "or a missing cstats.created()"); + } } static void gc() { // Force garbage collection to ensure any pending destructors are invoked: #if defined(PYPY_VERSION) PyObject *globals = PyEval_GetGlobals(); - PyObject *result = PyRun_String( - "import gc\n" - "for i in range(2):" - " gc.collect()\n", - Py_file_input, globals, globals); + PyObject *result = PyRun_String("import gc\n" + "for i in range(2):\n" + " gc.collect()\n", + Py_file_input, + globals, + globals); if (result == nullptr) throw py::error_already_set(); Py_DECREF(result); @@ -127,15 +131,18 @@ public: int alive() { gc(); int total = 0; - for (const auto &p : _instances) - if (p.second > 0) + for (const auto &p : _instances) { + if (p.second > 0) { total += p.second; + } + } return total; } void value() {} // Recursion terminator // Takes one or more values, converts them to strings, then stores them. - template <typename T, typename... Tmore> void value(const T &v, Tmore &&...args) { + template <typename T, typename... Tmore> + void value(const T &v, Tmore &&...args) { std::ostringstream oss; oss << v; _values.push_back(oss.str()); @@ -145,19 +152,22 @@ public: // Move out stored values py::list values() { py::list l; - for (const auto &v : _values) l.append(py::cast(v)); + for (const auto &v : _values) { + l.append(py::cast(v)); + } _values.clear(); return l; } // Gets constructor stats from a C++ type index - static ConstructorStats& get(std::type_index type) { + static ConstructorStats &get(std::type_index type) { static std::unordered_map<std::type_index, ConstructorStats> all_cstats; return all_cstats[type]; } // Gets constructor stats from a C++ type - template <typename T> static ConstructorStats& get() { + template <typename T> + static ConstructorStats &get() { #if defined(PYPY_VERSION) gc(); #endif @@ -165,11 +175,12 @@ public: } // Gets constructor stats from a Python class - static ConstructorStats& get(py::object class_) { + static ConstructorStats &get(py::object class_) { auto &internals = py::detail::get_internals(); const std::type_index *t1 = nullptr, *t2 = nullptr; try { - auto *type_info = internals.registered_types_py.at((PyTypeObject *) class_.ptr()).at(0); + auto *type_info + = internals.registered_types_py.at((PyTypeObject *) class_.ptr()).at(0); for (auto &p : internals.registered_types_cpp) { if (p.second == type_info) { if (t1) { @@ -179,17 +190,23 @@ public: t1 = &p.first; } } + } catch (const std::out_of_range &) { + } + if (!t1) { + throw std::runtime_error("Unknown class passed to ConstructorStats::get()"); } - catch (const std::out_of_range&) {} - if (!t1) throw std::runtime_error("Unknown class passed to ConstructorStats::get()"); auto &cs1 = get(*t1); - // If we have both a t1 and t2 match, one is probably the trampoline class; return whichever - // has more constructions (typically one or the other will be 0) + // If we have both a t1 and t2 match, one is probably the trampoline class; return + // whichever has more constructions (typically one or the other will be 0) if (t2) { auto &cs2 = get(*t2); - int cs1_total = cs1.default_constructions + cs1.copy_constructions + cs1.move_constructions + (int) cs1._values.size(); - int cs2_total = cs2.default_constructions + cs2.copy_constructions + cs2.move_constructions + (int) cs2._values.size(); - if (cs2_total > cs1_total) return cs2; + int cs1_total = cs1.default_constructions + cs1.copy_constructions + + cs1.move_constructions + (int) cs1._values.size(); + int cs2_total = cs2.default_constructions + cs2.copy_constructions + + cs2.move_constructions + (int) cs2._values.size(); + if (cs2_total > cs1_total) { + return cs2; + } } return cs1; } @@ -198,78 +215,108 @@ public: // To track construction/destruction, you need to call these methods from the various // constructors/operators. The ones that take extra values record the given values in the // constructor stats values for later inspection. -template <class T> void track_copy_created(T *inst) { ConstructorStats::get<T>().copy_created(inst); } -template <class T> void track_move_created(T *inst) { ConstructorStats::get<T>().move_created(inst); } -template <class T, typename... Values> void track_copy_assigned(T *, Values &&...values) { +template <class T> +void track_copy_created(T *inst) { + ConstructorStats::get<T>().copy_created(inst); +} +template <class T> +void track_move_created(T *inst) { + ConstructorStats::get<T>().move_created(inst); +} +template <class T, typename... Values> +void track_copy_assigned(T *, Values &&...values) { auto &cst = ConstructorStats::get<T>(); cst.copy_assignments++; cst.value(std::forward<Values>(values)...); } -template <class T, typename... Values> void track_move_assigned(T *, Values &&...values) { +template <class T, typename... Values> +void track_move_assigned(T *, Values &&...values) { auto &cst = ConstructorStats::get<T>(); cst.move_assignments++; cst.value(std::forward<Values>(values)...); } -template <class T, typename... Values> void track_default_created(T *inst, Values &&...values) { +template <class T, typename... Values> +void track_default_created(T *inst, Values &&...values) { auto &cst = ConstructorStats::get<T>(); cst.default_created(inst); cst.value(std::forward<Values>(values)...); } -template <class T, typename... Values> void track_created(T *inst, Values &&...values) { +template <class T, typename... Values> +void track_created(T *inst, Values &&...values) { auto &cst = ConstructorStats::get<T>(); cst.created(inst); cst.value(std::forward<Values>(values)...); } -template <class T, typename... Values> void track_destroyed(T *inst) { +template <class T, typename... Values> +void track_destroyed(T *inst) { ConstructorStats::get<T>().destroyed(inst); } -template <class T, typename... Values> void track_values(T *, Values &&...values) { +template <class T, typename... Values> +void track_values(T *, Values &&...values) { ConstructorStats::get<T>().value(std::forward<Values>(values)...); } /// Don't cast pointers to Python, print them as strings inline const char *format_ptrs(const char *p) { return p; } template <typename T> -py::str format_ptrs(T *p) { return "{:#x}"_s.format(reinterpret_cast<std::uintptr_t>(p)); } +py::str format_ptrs(T *p) { + return "{:#x}"_s.format(reinterpret_cast<std::uintptr_t>(p)); +} template <typename T> -auto format_ptrs(T &&x) -> decltype(std::forward<T>(x)) { return std::forward<T>(x); } +auto format_ptrs(T &&x) -> decltype(std::forward<T>(x)) { + return std::forward<T>(x); +} template <class T, typename... Output> void print_constr_details(T *inst, const std::string &action, Output &&...output) { - py::print("###", py::type_id<T>(), "@", format_ptrs(inst), action, + py::print("###", + py::type_id<T>(), + "@", + format_ptrs(inst), + action, format_ptrs(std::forward<Output>(output))...); } // Verbose versions of the above: -template <class T, typename... Values> void print_copy_created(T *inst, Values &&...values) { // NB: this prints, but doesn't store, given values +template <class T, typename... Values> +void print_copy_created(T *inst, + Values &&...values) { // NB: this prints, but doesn't store, given values print_constr_details(inst, "created via copy constructor", values...); track_copy_created(inst); } -template <class T, typename... Values> void print_move_created(T *inst, Values &&...values) { // NB: this prints, but doesn't store, given values +template <class T, typename... Values> +void print_move_created(T *inst, + Values &&...values) { // NB: this prints, but doesn't store, given values print_constr_details(inst, "created via move constructor", values...); track_move_created(inst); } -template <class T, typename... Values> void print_copy_assigned(T *inst, Values &&...values) { +template <class T, typename... Values> +void print_copy_assigned(T *inst, Values &&...values) { print_constr_details(inst, "assigned via copy assignment", values...); track_copy_assigned(inst, values...); } -template <class T, typename... Values> void print_move_assigned(T *inst, Values &&...values) { +template <class T, typename... Values> +void print_move_assigned(T *inst, Values &&...values) { print_constr_details(inst, "assigned via move assignment", values...); track_move_assigned(inst, values...); } -template <class T, typename... Values> void print_default_created(T *inst, Values &&...values) { +template <class T, typename... Values> +void print_default_created(T *inst, Values &&...values) { print_constr_details(inst, "created via default constructor", values...); track_default_created(inst, values...); } -template <class T, typename... Values> void print_created(T *inst, Values &&...values) { +template <class T, typename... Values> +void print_created(T *inst, Values &&...values) { print_constr_details(inst, "created", values...); track_created(inst, values...); } -template <class T, typename... Values> void print_destroyed(T *inst, Values &&...values) { // Prints but doesn't store given values +template <class T, typename... Values> +void print_destroyed(T *inst, Values &&...values) { // Prints but doesn't store given values print_constr_details(inst, "destroyed", values...); track_destroyed(inst); } -template <class T, typename... Values> void print_values(T *inst, Values &&...values) { +template <class T, typename... Values> +void print_values(T *inst, Values &&...values) { print_constr_details(inst, ":", values...); track_values(inst, values...); } |